NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / winnt / nh340key.c
blobb79a4a1fc8c5ba241e4fa9d5314b3e0222a65bda
1 /* aNetHack 0.0.1 nh340key.c $ANH-Date: 1432512793 2015/05/25 00:13:13 $ $ANH-Branch: master $:$ANH-Revision: 1.12 $ */
2 /* Copyright (c) aNetHack PC Development Team 2003 */
3 /* aNetHack may be freely redistributed. See license for details. */
5 /*
6 * This is the aNetHack keystroke processing from aNetHack 3.4.0.
7 * It can be built as a run-time loadable dll (nh340key.dll),
8 * placed in the same directory as the anethack.exe executable,
9 * and loaded by specifying OPTIONS=altkeyhandler:nh340key
10 * in defaults.nh
13 static char where_to_get_source[] = "http://www.anethack.org/";
14 static char author[] = "The aNetHack Development Team";
16 #include "hack.h"
17 #include "wintty.h"
18 #include "win32api.h"
20 extern HANDLE hConIn;
21 extern INPUT_RECORD ir;
22 char dllname[512];
23 char *shortdllname;
25 int FDECL(__declspec(dllexport) __stdcall ProcessKeystroke,
26 (HANDLE hConIn, INPUT_RECORD *ir, boolean *valid,
27 BOOLEAN_P numberpad, int portdebug));
29 int WINAPI
30 DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
32 char dlltmpname[512];
33 char *tmp = dlltmpname, *tmp2;
34 *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
35 (void) strcpy(dllname, tmp);
36 tmp2 = strrchr(dllname, '\\');
37 if (tmp2) {
38 tmp2++;
39 shortdllname = tmp2;
41 return TRUE;
45 * Keyboard translation tables.
46 * (Adopted from the MSDOS port)
49 #define KEYPADLO 0x47
50 #define KEYPADHI 0x53
52 #define PADKEYS (KEYPADHI - KEYPADLO + 1)
53 #define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
56 * Keypad keys are translated to the normal values below.
57 * Shifted keypad keys are translated to the
58 * shift values below.
61 static const struct pad {
62 uchar normal, shift, cntrl;
63 } keypad[PADKEYS] =
65 { 'y', 'Y', C('y') }, /* 7 */
66 { 'k', 'K', C('k') }, /* 8 */
67 { 'u', 'U', C('u') }, /* 9 */
68 { 'm', C('p'), C('p') }, /* - */
69 { 'h', 'H', C('h') }, /* 4 */
70 { 'g', 'G', 'g' }, /* 5 */
71 { 'l', 'L', C('l') }, /* 6 */
72 { '+', 'P', C('p') }, /* + */
73 { 'b', 'B', C('b') }, /* 1 */
74 { 'j', 'J', C('j') }, /* 2 */
75 { 'n', 'N', C('n') }, /* 3 */
76 { 'i', 'I', C('i') }, /* Ins */
77 { '.', ':', ':' } /* Del */
79 numpad[PADKEYS] = {
80 { '7', M('7'), '7' }, /* 7 */
81 { '8', M('8'), '8' }, /* 8 */
82 { '9', M('9'), '9' }, /* 9 */
83 { 'm', C('p'), C('p') }, /* - */
84 { '4', M('4'), '4' }, /* 4 */
85 { 'g', 'G', 'g' }, /* 5 */
86 { '6', M('6'), '6' }, /* 6 */
87 { '+', 'P', C('p') }, /* + */
88 { '1', M('1'), '1' }, /* 1 */
89 { '2', M('2'), '2' }, /* 2 */
90 { '3', M('3'), '3' }, /* 3 */
91 { 'i', 'I', C('i') }, /* Ins */
92 { '.', ':', ':' } /* Del */
95 #define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
97 int __declspec(dllexport) __stdcall ProcessKeystroke(hConIn, ir, valid,
98 numberpad, portdebug)
99 HANDLE hConIn;
100 INPUT_RECORD *ir;
101 boolean *valid;
102 boolean numberpad;
103 int portdebug;
105 int metaflags = 0, k = 0;
106 int keycode, vk;
107 unsigned char ch, pre_ch, mk = 0;
108 unsigned short int scan;
109 unsigned long shiftstate;
110 int altseq = 0;
111 const struct pad *kpad;
113 shiftstate = 0L;
114 ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
115 scan = ir->Event.KeyEvent.wVirtualScanCode;
116 vk = ir->Event.KeyEvent.wVirtualKeyCode;
117 keycode = MapVirtualKey(vk, 2);
118 shiftstate = ir->Event.KeyEvent.dwControlKeyState;
120 if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
121 if (ch || inmap(keycode, vk))
122 altseq = 1;
123 else
124 altseq = -1; /* invalid altseq */
126 if (ch || (iskeypad(scan)) || (altseq > 0))
127 *valid = TRUE;
128 /* if (!valid) return 0; */
130 * shiftstate can be checked to see if various special
131 * keys were pressed at the same time as the key.
132 * Currently we are using the ALT & SHIFT & CONTROLS.
134 * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
135 * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
136 * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
137 * CAPSLOCK_ON, ENHANCED_KEY
139 * are all valid bit masks to use on shiftstate.
140 * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
141 * left control key was pressed with the keystroke.
143 if (iskeypad(scan)) {
144 kpad = numberpad ? numpad : keypad;
145 if (shiftstate & SHIFT_PRESSED) {
146 ch = kpad[scan - KEYPADLO].shift;
147 } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
148 ch = kpad[scan - KEYPADLO].cntrl;
149 } else {
150 ch = kpad[scan - KEYPADLO].normal;
152 } else if (altseq > 0) { /* ALT sequence */
153 if (vk == 0xBF)
154 ch = M('?');
155 else
156 ch = M(tolower((uchar) keycode));
158 if (ch == '\r')
159 ch = '\n';
160 #ifdef PORT_DEBUG
161 if (portdebug) {
162 char buf[BUFSZ];
163 Sprintf(buf,
164 "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, sh=0x%X (ESC to end)",
165 shortdllname, ch, scan, vk, shiftstate);
166 fprintf(stdout, "\n%s", buf);
168 #endif
169 return ch;
172 int __declspec(dllexport) __stdcall NHkbhit(hConIn, ir)
173 HANDLE hConIn;
174 INPUT_RECORD *ir;
176 int done = 0; /* true = "stop searching" */
177 int retval; /* true = "we had a match" */
178 DWORD count;
179 unsigned short int scan;
180 unsigned char ch;
181 unsigned long shiftstate;
182 int altseq = 0, keycode, vk;
183 done = 0;
184 retval = 0;
185 while (!done) {
186 count = 0;
187 PeekConsoleInput(hConIn, ir, 1, &count);
188 if (count > 0) {
189 if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
190 ch = ir->Event.KeyEvent.uChar.AsciiChar;
191 scan = ir->Event.KeyEvent.wVirtualScanCode;
192 shiftstate = ir->Event.KeyEvent.dwControlKeyState;
193 vk = ir->Event.KeyEvent.wVirtualKeyCode;
194 keycode = MapVirtualKey(vk, 2);
195 if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
196 if (ch || inmap(keycode, vk))
197 altseq = 1;
198 else
199 altseq = -1; /* invalid altseq */
201 if (ch || iskeypad(scan) || altseq) {
202 done = 1; /* Stop looking */
203 retval = 1; /* Found what we sought */
204 } else {
205 /* Strange Key event; let's purge it to avoid trouble */
206 ReadConsoleInput(hConIn, ir, 1, &count);
209 } else if ((ir->EventType == MOUSE_EVENT
210 && (ir->Event.MouseEvent.dwButtonState
211 & MOUSEMASK))) {
212 done = 1;
213 retval = 1;
216 else /* Discard it, it's an insignificant event */
217 ReadConsoleInput(hConIn, ir, 1, &count);
218 } else /* There are no events in console event queue */ {
219 done = 1; /* Stop looking */
220 retval = 0;
223 return retval;
226 int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
227 mode, mod, cc)
228 HANDLE hConIn;
229 INPUT_RECORD *ir;
230 DWORD *count;
231 boolean numpad;
232 int mode;
233 int *mod;
234 coord *cc;
236 #if defined(SAFERHANGUP)
237 DWORD dwWait;
238 #endif
239 int ch;
240 boolean valid = 0, done = 0;
241 while (!done) {
242 #if defined(SAFERHANGUP)
243 dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
244 INFINITE, // waits indefinitely
245 TRUE); // alertable wait enabled
246 if (dwWait == WAIT_FAILED)
247 return '\033';
248 #endif
249 ReadConsoleInput(hConIn, ir, 1, count);
250 if (mode == 0) {
251 if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
252 ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
253 done = valid;
255 } else {
256 if (count > 0) {
257 if (ir->EventType == KEY_EVENT
258 && ir->Event.KeyEvent.bKeyDown) {
259 ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
260 if (valid)
261 return ch;
262 } else if (ir->EventType == MOUSE_EVENT) {
263 if ((ir->Event.MouseEvent.dwEventFlags == 0)
264 && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
265 cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
266 cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
268 if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
269 *mod = CLICK_1;
270 else if (ir->Event.MouseEvent.dwButtonState
271 & RIGHTBUTTON)
272 *mod = CLICK_2;
273 #if 0 /* middle button */
274 else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
275 *mod = CLICK_3;
276 #endif
277 return 0;
280 } else
281 done = 1;
284 return mode ? 0 : ch;
287 int __declspec(dllexport) __stdcall SourceWhere(buf)
288 char **buf;
290 if (!buf)
291 return 0;
292 *buf = where_to_get_source;
293 return 1;
296 int __declspec(dllexport) __stdcall SourceAuthor(buf)
297 char **buf;
299 if (!buf)
300 return 0;
301 *buf = author;
302 return 1;
305 int __declspec(dllexport) __stdcall KeyHandlerName(buf, full)
306 char **buf;
307 int full;
309 if (!buf)
310 return 0;
311 if (full)
312 *buf = dllname;
313 else
314 *buf = shortdllname;
315 return 1;