1 /* $Id: key.c,v 1.3 2004-05-22 22:58:09 btb Exp $ */
2 #define WIN32_LEAN_AND_MEAN
11 extern void PumpMessages(void);
13 // These are to kludge up a bit my slightly broken GCC directx port.
15 #define E_FAIL (HRESULT)0x80004005L
18 #define SUCCEEDED(a) ((HRESULT)(a) >= 0)
25 extern void PumpMessages(void);
27 volatile int keyd_time_when_last_pressed;
28 volatile unsigned char keyd_last_pressed;
29 volatile unsigned char keyd_last_released;
30 volatile unsigned char keyd_pressed [256];
31 unsigned char keyd_repeat;
32 unsigned char WMKey_Handler_Ready=0;
35 fix g_rgtimeDown [256];
36 fix g_rgtimeElapsed [256];
37 ULONG g_rgcDowns [256];
40 char ascii_table[256];
41 char shifted_ascii_table[256];
44 LPDIRECTINPUTDEVICE g_lpdidKeybd;
49 #define KEY_BUFFER_SIZE 16
51 ULONG g_rgbKeyQueue [KEY_BUFFER_SIZE];
52 fix g_rgtimeQueue [KEY_BUFFER_SIZE];
53 ULONG g_rgbPressedQueue [KEY_BUFFER_SIZE];
55 ULONG iQueueStart = 0;
58 KEYCODE ShiftKeyCode (KEYCODE kcKey)
62 if (keyd_pressed [kcKey])
67 if (keyd_pressed [KEY_LSHIFT] || keyd_pressed [KEY_RSHIFT])
69 kcShifted |= KEY_SHIFTED;
71 if (keyd_pressed [KEY_LCTRL] || keyd_pressed [KEY_RCTRL])
73 kcShifted |= KEY_CTRLED;
75 if (keyd_pressed [KEY_LALT] || keyd_pressed [KEY_RALT])
77 kcShifted |= KEY_ALTED;
92 return iQueueEnd != KEY_BUFFER_SIZE - 1;
96 return iQueueEnd != iQueueStart - 1;
100 void FlushQueue (void)
102 iQueueStart = iQueueEnd = 0;
105 void PushKey (ULONG kcKey, fix timeDown)
107 if (SpaceInBuffer ())
109 g_rgbKeyQueue [iQueueEnd] = ShiftKeyCode(kcKey);
110 g_rgtimeQueue [iQueueEnd] = timeDown;
112 if (iQueueEnd ++ == KEY_BUFFER_SIZE)
119 BOOL PopKey (KEYCODE *piKey, fix *ptimeDown)
121 if (iQueueEnd != iQueueStart)
123 // there are items in the queue
127 *piKey = g_rgbKeyQueue [iQueueStart];
129 if (ptimeDown != NULL)
131 *ptimeDown = g_rgbPressedQueue [iQueueStart];
134 if (iQueueStart ++ == KEY_BUFFER_SIZE)
147 static BOOL EnsureInit (void)
149 if (g_lpdidKeybd == NULL)
154 return g_lpdidKeybd != NULL;
157 void key_close(void);
162 // my kingdom, my kingdom for C++...
163 if (SUCCEEDED (hr = DirectInputCreate (GetModuleHandle (NULL), DIRECTINPUT_VERSION, &g_lpdi, NULL)))
165 if (SUCCEEDED (hr = IDirectInput_CreateDevice (g_lpdi, (void *)&GUID_SysKeyboard, &g_lpdidKeybd, NULL)))
169 dipdw.diph.dwSize = sizeof (DIPROPDWORD);
170 dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER);
171 dipdw.diph.dwObj = 0;
172 dipdw.diph.dwHow = DIPH_DEVICE;
175 if (SUCCEEDED (hr = IDirectInputDevice_SetDataFormat (g_lpdidKeybd, &c_dfDIKeyboard)) &&
176 SUCCEEDED (hr = IDirectInputDevice_SetCooperativeLevel (g_lpdidKeybd, g_hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)) &&
177 SUCCEEDED (hr = IDirectInputDevice_SetProperty (g_lpdidKeybd, DIPROP_BUFFERSIZE, &dipdw.diph)) &&
178 SUCCEEDED (hr = IDirectInputDevice_Acquire (g_lpdidKeybd)))
181 WMKey_Handler_Ready = 1;
183 // Clear the keyboard array
190 IDirectInputDevice_Release (g_lpdidKeybd);
199 WMKey_Handler_Ready = 0;
200 if (g_lpdidKeybd != NULL)
202 IDirectInputDevice_Unacquire (g_lpdidKeybd);
203 IDirectInputDevice_Release (g_lpdidKeybd);
208 IDirectInput_Release (g_lpdi);
213 HRESULT ReadKey (DIDEVICEOBJECTDATA *pdidod)
217 if (g_lpdidKeybd == NULL)
219 hr = IDirectInputDevice_Acquire (g_lpdidKeybd);
222 hr = IDirectInputDevice_GetDeviceData (
228 if (SUCCEEDED (hr) && cElements != 1)
235 void UpdateState (DIDEVICEOBJECTDATA *pdidod)
237 KEYCODE kcKey = pdidod->dwOfs;
239 fix timeNow = timer_get_fixed_seconds ();
241 if (pdidod->dwData & 0x80)
243 keyd_pressed [kcKey] = 1;
244 keyd_last_pressed = kcKey;
245 g_rgtimeDown [kcKey] = keyd_time_when_last_pressed = timeNow;
246 g_rgcDowns [kcKey] ++;
247 PushKey (kcKey, keyd_time_when_last_pressed);
251 keyd_pressed [kcKey] = 0;
252 keyd_last_released = kcKey;
254 g_rgtimeElapsed [kcKey] = timeNow - g_rgtimeDown [kcKey];
258 void keyboard_handler()
260 // static int peekmsgcount = 0;
261 DIDEVICEOBJECTDATA didod;
262 while (SUCCEEDED (ReadKey (&didod)))
264 UpdateState (&didod);
266 //added 02/20/99 by adb to prevent message overflow
267 //(this should probably go somewhere else...)
268 // if (++peekmsgcount == 64) // 64 = wild guess...
283 DWORD cElements = INFINITE;
286 IDirectInputDevice_GetDeviceData(
288 sizeof (DIDEVICEOBJECTDATA),
293 for (kcKey = 0; kcKey < 256; kcKey ++)
295 g_rgtimeElapsed [kcKey] = 0;
296 g_rgcDowns [kcKey] = 0;
297 g_rgcUps [kcKey] = 0;
298 keyd_pressed [kcKey] = 0;
309 while (!PopKey (&kcKey, NULL))
317 KEYCODE key_inkey_time(fix * pTime)
323 PopKey (&kcKey, pTime);
330 return key_inkey_time (NULL);
333 KEYCODE key_peekkey ()
344 unsigned char key_to_ascii(KEYCODE kcKey )
346 BOOL bShifted = kcKey & KEY_SHIFTED;
349 kcKey &= ~KEY_SHIFTED;
355 ch = shifted_ascii_table [kcKey & 0xff];
359 ch = ascii_table [kcKey & 0xff];
370 // Returns the number of seconds this key has been down since last call.
371 fix key_down_time(KEYCODE kcKey)
375 if ((kcKey<0) || (kcKey>127)) return 0;
377 if (keyd_pressed [kcKey])
379 fix timeNow = timer_get_fixed_seconds ();
380 timeElapsed = timeNow - g_rgtimeDown [kcKey];
381 g_rgtimeDown [kcKey] = timeNow;
385 timeElapsed = g_rgtimeElapsed [kcKey];
386 g_rgtimeElapsed [kcKey] = 0;
393 unsigned int key_down_count(KEYCODE kcKey)
397 if ((kcKey < 0) || (kcKey > 127))
403 n = g_rgcDowns [kcKey];
404 g_rgcDowns [kcKey] = 0;
410 unsigned int key_up_count(KEYCODE kcKey)
415 if ((kcKey < 0) || (kcKey > 127))
421 n = g_rgcUps [kcKey];
422 g_rgcUps [kcKey] = 0;
429 #define ___ ((char) 255)
430 char ascii_table[256] =
432 ___, ___, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', ___, ___,
433 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', ___, ___, 'a', 's',
434 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', ___,'\\', 'z', 'x', 'c', 'v',
435 'b', 'n', 'm', ',', '.', '/', ___, '*', ___, ' ', ___, ___, ___, ___, ___, ___,
436 ___, ___, ___, ___, ___, ___, ___, '7', '8', '9', '-', '4', '5', '6', '+', '1',
437 '2', '3', '0', '.', ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
438 ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
439 ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
442 char shifted_ascii_table[256] =
444 ___, ___, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', ___, ___,
445 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', ___, ___, 'A', 'S',
446 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':','\"', '~', ___, '|', 'Z', 'X', 'C', 'V',
447 'B', 'N', 'M', '<', '>', '?', ___, '*', ___, ' ', ___, ___, ___, ___, ___, ___,
448 ___, ___, ___, ___, ___, ___, ___, '&', '*', '(', '_', '$', '%', '^', '=', '!',
449 '@', '#', ')', '>', ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
450 ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
451 ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___,
455 char * key_text[256] = {
456 "","ESC","1","2","3","4","5","6","7","8","9","0","-",
457 "=","BSPC","TAB","Q","W","E","R","T","Y","U","I","O",
458 "P","[","]","
\83","LCTRL","A","S","D","F",
459 "G","H","J","K","L",";","'","`",
460 "LSHFT","\\","Z","X","C","V","B","N","M",",",
461 ".","/","RSHFT","PAD*","LALT","SPC",
462 "CPSLK","F1","F2","F3","F4","F5","F6","F7","F8","F9",
463 "F10","NMLCK","SCLK","PAD7","PAD8","PAD9","PAD-",
464 "PAD4","PAD5","PAD6","PAD+","PAD1","PAD2","PAD3","PAD0",
465 "PAD.","","","","F11","F12","","","","","","","","","",
466 "","","","","","","","","","","","","","","","","","","","",
467 "","","","","","","","","","","","","","","","","","","","",
468 "","","","","","","","","","","","","","","","","","",
469 "PAD
\83","RCTRL","","","","","","","","","","","","","",
470 "","","","","","","","","","","PAD/","","","RALT","",
471 "","","","","","","","","","","","","","HOME","
\82","PGUP",
472 "","
\81","","
\7f","","END","
\80","PGDN","INS",
473 "DEL","","","","","","","","","","","","","","","","","",
474 "","","","","","","","","","","","","","","","","","","","",
475 "","","","","","","" };
476 #if 0 // what was this? -- adb
477 "","","","HOME","UP","PGUP","","LEFT","","RGHT","","END","DOWN","PGDN","INS","DEL",
478 "","
\81","","
\7f","","","?","","",
479 "","","","","","","","","","","","","","","","","","",
480 "","","","","","","","","","","","","","","","","","","","",
481 "","","","","","","" };