OSDN Git Service

no bone
[nethackexpress/trunk.git] / sys / winnt / nhdefkey.c
1 /*      SCCS Id: @(#)nhdefkey.c 3.4     $Date: 2003/11/01 23:57:00 $   */
2 /* Copyright (c) NetHack PC Development Team 2003                      */
3 /* NetHack may be freely redistributed.  See license for details.      */
4
5 /*
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.
10  *
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.
16  *
17  */
18
19 static char where_to_get_source[] = "http://www.nethack.org/";
20 static char author[] = "The NetHack Development Team";
21
22 #include "hack.h"
23 #include "wintty.h"
24 #include "win32api.h"
25
26 extern HANDLE hConIn;
27 extern INPUT_RECORD ir;
28 char dllname[512];
29 char *shortdllname;
30
31 int FDECL(__declspec(dllexport) __stdcall
32 ProcessKeystroke, (HANDLE hConIn, INPUT_RECORD *ir, 
33     boolean *valid, BOOLEAN_P numberpad, int portdebug));
34
35 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
36 {
37         char dlltmpname[512];
38         char *tmp = dlltmpname, *tmp2;
39         *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
40         (void)strcpy(dllname, tmp);
41         tmp2 = strrchr(dllname, '\\');
42         if (tmp2) {
43                 tmp2++;
44                 shortdllname = tmp2;
45         }
46         return TRUE;
47 }
48
49 /*
50  *  Keyboard translation tables.
51  *  (Adopted from the MSDOS port)
52  */
53
54 #define KEYPADLO        0x47
55 #define KEYPADHI        0x53
56
57 #define PADKEYS         (KEYPADHI - KEYPADLO + 1)
58 #define iskeypad(x)     (KEYPADLO <= (x) && (x) <= KEYPADHI)
59
60 /*
61  * Keypad keys are translated to the normal values below.
62  * Shifted keypad keys are translated to the
63  *    shift values below.
64  */
65
66 static const struct pad {
67         uchar normal, shift, cntrl;
68 } keypad[PADKEYS] = {
69                         {'y', 'Y', C('y')},             /* 7 */
70                         {'k', 'K', C('k')},             /* 8 */
71                         {'u', 'U', C('u')},             /* 9 */
72                         {'m', C('p'), C('p')},          /* - */
73                         {'h', 'H', C('h')},             /* 4 */
74                         {'g', 'G', 'g'},                /* 5 */
75                         {'l', 'L', C('l')},             /* 6 */
76                         {'+', 'P', C('p')},             /* + */
77                         {'b', 'B', C('b')},             /* 1 */
78                         {'j', 'J', C('j')},             /* 2 */
79                         {'n', 'N', C('n')},             /* 3 */
80                         {'i', 'I', C('i')},             /* Ins */
81                         {'.', ':', ':'}                 /* Del */
82 }, numpad[PADKEYS] = {
83                         {'7', M('7'), '7'},             /* 7 */
84                         {'8', M('8'), '8'},             /* 8 */
85                         {'9', M('9'), '9'},             /* 9 */
86                         {'m', C('p'), C('p')},          /* - */
87                         {'4', M('4'), '4'},             /* 4 */
88                         {'5', M('5'), '5'},             /* 5 */
89                         {'6', M('6'), '6'},             /* 6 */
90                         {'+', 'P', C('p')},             /* + */
91                         {'1', M('1'), '1'},             /* 1 */
92                         {'2', M('2'), '2'},             /* 2 */
93                         {'3', M('3'), '3'},             /* 3 */
94                         {'0', M('0'), '0'},             /* Ins */
95                         {'.', ':', ':'}                 /* Del */
96 };
97
98 #define inmap(x,vk)     (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
99
100 static BYTE KeyState[256];
101
102 int __declspec(dllexport) __stdcall
103 ProcessKeystroke(hConIn,ir, valid, numberpad, portdebug)
104 HANDLE hConIn;
105 INPUT_RECORD *ir;
106 boolean *valid;
107 boolean numberpad;
108 int portdebug;
109 {
110         int metaflags = 0, k = 0;
111         int keycode, vk;
112         unsigned char ch, pre_ch, mk = 0;
113         unsigned short int scan;
114         unsigned long shiftstate;
115         int altseq = 0;
116         const struct pad *kpad;
117
118         shiftstate = 0L;
119         ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
120         scan  = ir->Event.KeyEvent.wVirtualScanCode;
121         vk    = ir->Event.KeyEvent.wVirtualKeyCode;
122         keycode = MapVirtualKey(vk, 2);
123         shiftstate = ir->Event.KeyEvent.dwControlKeyState;
124         KeyState[VK_SHIFT]   = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0;
125         KeyState[VK_CONTROL] = (shiftstate & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) ?
126                                 0x81 : 0;
127         KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0;
128
129         if (shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) {
130                 if (ch || inmap(keycode,vk)) altseq = 1;
131                 else altseq = -1;       /* invalid altseq */
132         }
133         if (ch || (iskeypad(scan)) || (altseq > 0))
134                 *valid = TRUE;
135         /* if (!valid) return 0; */
136         /*
137          * shiftstate can be checked to see if various special
138          * keys were pressed at the same time as the key.
139          * Currently we are using the ALT & SHIFT & CONTROLS.
140          *
141          *           RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
142          *           RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
143          *           SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
144          *           CAPSLOCK_ON, ENHANCED_KEY
145          *
146          * are all valid bit masks to use on shiftstate.
147          * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
148          *      left control key was pressed with the keystroke.
149          */
150         if (iskeypad(scan)) {
151             kpad = numberpad ? numpad : keypad;
152             if (shiftstate & SHIFT_PRESSED) {
153                 ch = kpad[scan - KEYPADLO].shift;
154             }
155             else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
156                 ch = kpad[scan - KEYPADLO].cntrl;
157             }
158             else {
159                 ch = kpad[scan - KEYPADLO].normal;
160             }
161         }
162         else if (altseq > 0) { /* ALT sequence */
163                 if (vk == 0xBF) ch = M('?');
164                 else ch = M(tolower(keycode));
165         }
166         /* Attempt to work better with international keyboards. */
167         else {
168                 WORD chr[2];
169                 k = ToAscii(vk, scan, KeyState, chr, 0);
170                 if (k <= 2)
171                     switch(k) {
172                         case 2:  /* two characters */
173                                 ch = (unsigned char)chr[1];
174                                 *valid = TRUE;
175                                 break;
176                         case 1:  /* one character */
177                                 ch = (unsigned char)chr[0];
178                                 *valid = TRUE;
179                                 break;
180                         case 0:  /* no translation */
181                         default: /* negative */
182                                 *valid = FALSE;
183                     }
184         }
185         if (ch == '\r') ch = '\n';
186 #ifdef PORT_DEBUG
187         if (portdebug) {
188                 char buf[BUFSZ];
189                 Sprintf(buf,
190         "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%X, ta=%d (ESC to end)",
191                         shortdllname, ch, scan, vk, pre_ch, shiftstate, k);
192                 fprintf(stdout, "\n%s", buf);
193         }
194 #endif
195         return ch;
196 }
197
198
199 int __declspec(dllexport) __stdcall
200 NHkbhit(hConIn, ir)
201 HANDLE hConIn;
202 INPUT_RECORD *ir;
203 {
204         int done = 0;   /* true =  "stop searching"        */
205         int retval;     /* true =  "we had a match"        */
206         DWORD count;
207         unsigned short int scan;
208         unsigned char ch;
209         unsigned long shiftstate;
210         int altseq = 0, keycode, vk;
211         done = 0;
212         retval = 0;
213         while (!done)
214         {
215             count = 0;
216             PeekConsoleInput(hConIn,ir,1,&count);
217             if (count > 0) {
218                 if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
219                         ch    = ir->Event.KeyEvent.uChar.AsciiChar;
220                         scan  = ir->Event.KeyEvent.wVirtualScanCode;
221                         shiftstate = ir->Event.KeyEvent.dwControlKeyState;
222                         vk = ir->Event.KeyEvent.wVirtualKeyCode;
223                         keycode = MapVirtualKey(vk, 2);
224                         if (shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) {
225                                 if  (ch || inmap(keycode,vk)) altseq = 1;
226                                 else altseq = -1;       /* invalid altseq */
227                         }
228                         if (ch || iskeypad(scan) || altseq) {
229                                 done = 1;           /* Stop looking         */
230                                 retval = 1;         /* Found what we sought */
231                         } else {
232                                 /* Strange Key event; let's purge it to avoid trouble */
233                                 ReadConsoleInput(hConIn,ir,1,&count);
234                         }
235
236                 }
237                 else if ((ir->EventType == MOUSE_EVENT &&
238                   (ir->Event.MouseEvent.dwButtonState & MOUSEMASK))) {
239                         done = 1;
240                         retval = 1;
241                 }
242
243                 else /* Discard it, it's an insignificant event */
244                         ReadConsoleInput(hConIn,ir,1,&count);
245                 } else  /* There are no events in console event queue */ {
246                 done = 1;         /* Stop looking               */
247                 retval = 0;
248             }
249         }
250         return retval;
251 }
252
253 int __declspec(dllexport) __stdcall
254 CheckInput(hConIn, ir, count, numpad, mode, mod, cc)
255 HANDLE hConIn;
256 INPUT_RECORD *ir;
257 DWORD *count; 
258 boolean numpad;
259 int mode;
260 int *mod;
261 coord *cc;
262 {
263         int ch;
264         boolean valid = 0, done = 0;
265         while (!done) {
266                 ReadConsoleInput(hConIn,ir,1,count);
267                 if (mode == 0) {
268                     if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
269                         ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
270                         done = valid;
271                     }
272                 } else {
273                     if (count > 0) {
274                         if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
275                             ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
276                             if (valid) return ch;
277                         } else if (ir->EventType == MOUSE_EVENT) {
278                             if ((ir->Event.MouseEvent.dwEventFlags == 0) &&
279                                 (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
280                                     cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
281                                     cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
282
283                                     if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
284                                         *mod = CLICK_1;
285                                     else if (ir->Event.MouseEvent.dwButtonState & RIGHTBUTTON)
286                                         *mod = CLICK_2;
287 #if 0   /* middle button */
288                                     else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
289                                         *mod = CLICK_3;
290 #endif 
291                                    return 0;
292                             }
293                         }
294                     } else 
295                         done = 1;
296                 }
297         }
298         return mode ? 0 : ch;
299 }
300
301 int __declspec(dllexport) __stdcall
302 SourceWhere(buf)
303 char **buf;
304 {
305         if (!buf) return 0;
306         *buf = where_to_get_source;
307         return 1;
308 }
309
310 int __declspec(dllexport) __stdcall
311 SourceAuthor(buf)
312 char **buf;
313 {
314         if (!buf) return 0;
315         *buf = author;
316         return 1;
317 }
318
319 int __declspec(dllexport) __stdcall
320 KeyHandlerName(buf, full)
321 char **buf;
322 int full;
323 {
324         if (!buf) return 0;
325         if (full) *buf = dllname;
326         else *buf = shortdllname;
327         return 1;
328 }
329