1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Shared helper routines for converting PC keyboard scancodes
12 * into a format that the main keyboard.c can understand, using
13 * the mapping tables from keyboard.dat.
14 *
15 * By Shawn Hargreaves.
16 *
17 * Salvador Eduardo Tropea added support for extended scancodes,
18 * keyboard LED's, capslock and numlock, and alt+numpad input.
19 *
20 * Fabian Nunez added support for the special Microsoft keys.
21 *
22 * Mathieu Lafon added support for the Pause and PrtScr keys and
23 * changed the key[] table to a normal/extended bitfield.
24 *
25 * Dynamic keyboard switching by Peter Cech.
26 *
27 * Peter Pavlovic improved the handling of accented keymaps.
28 *
29 * See readme.txt for copyright information.
30 */
31
32
33 #include <string.h>
34
35 #include "allegro.h"
36 #include "allegro/internal/aintern.h"
37
38
39
40 #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG)
41 #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG)
42 #define KB_ACCENTS (KB_ACCENT1_FLAG | KB_ACCENT2_FLAG | KB_ACCENT3_FLAG | KB_ACCENT4_FLAG)
43 #define KB_SH_CTRL_ALT (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG)
44 #define KB_CTRL_ALT (KB_CTRL_FLAG | KB_ALT_FLAG)
45
46
47 static int key_extended = FALSE;
48 static int key_altgr = FALSE;
49 static int key_pad_seq = 0;
50 static int key_pause_loop = 0;
51 static int key_paused = FALSE;
52
53 int _key_accent1 = 0;
54 int _key_accent2 = 0;
55 int _key_accent3 = 0;
56 int _key_accent4 = 0;
57
58 int _key_accent1_flag = 0;
59 int _key_accent2_flag = 0;
60 int _key_accent3_flag = 0;
61 int _key_accent4_flag = 0;
62
63 int _key_standard_kb = TRUE;
64
65 char *_keyboard_layout = NULL;
66
67 /* lookup table for converting hardware scancodes into Allegro format */
68 static unsigned char hw_to_mycode[128] =
69 {
70 /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
71 /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
72 /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
73 /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
74 /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
75 /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
76 /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
77 /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
78 /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
79 /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
80 /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
81 /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
82 /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
83 /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
84 /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
85 /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
86 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
87 /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
88 /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
89 /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
90 /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
91 /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
92 /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
93 /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
94 /* 0x60 */ 0, 0, 0, 0,
95 /* 0x64 */ 0, 0, 0, 0,
96 /* 0x68 */ 0, 0, 0, 0,
97 /* 0x6C */ 0, 0, 0, 0,
98 /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
99 /* 0x74 */ 0, 0, 0, 0,
100 /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
101 /* 0x7C */ 0, KEY_YEN, 0, 0
102 };
103
104
105
106 /* lookup table for converting extended hardware codes into Allegro format */
107 static unsigned char hw_to_mycode_ex[128] =
108 {
109 /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
110 /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
111 /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
112 /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
113 /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R,
114 /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I,
115 /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
116 /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S,
117 /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
118 /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
119 /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH,
120 /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
121 /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
122 /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR,
123 /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
124 /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
125 /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
126 /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME,
127 /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT,
128 /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END,
129 /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
130 /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
131 /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
132 /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
133 /* 0x60 */ 0, 0, 0, 0,
134 /* 0x64 */ 0, 0, 0, 0,
135 /* 0x68 */ 0, 0, 0, 0,
136 /* 0x6C */ 0, 0, 0, 0,
137 /* 0x70 */ 0, 0, 0, 0,
138 /* 0x74 */ 0, 0, 0, 0,
139 /* 0x78 */ 0, 0, 0, 0,
140 /* 0x7C */ 0, 0, 0, 0
141 };
142
143
144
145 /* convert Allegro format scancodes into key_shifts flag bits */
146 static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] =
147 {
148 KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG,
149 KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG,
150 KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG,
151 KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG
152 };
153
154
155
156 /* convert numeric pad scancodes into arrow codes */
157 static unsigned char numlock_table[10] =
158 {
159 KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT,
160 KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP
161 };
162
163
164
165 /* default mapping table for the US keyboard layout */
166 static unsigned short standard_key_ascii_table[KEY_MAX] =
167 {
168 /* start */ 0,
169 /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
170 /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
171 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
172 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
173 /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
174 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
175 /* numpad */ '/', '*', '-', '+', '.', 13,
176 /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0,
177 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
178 };
179
180
181
182 /* capslock mapping table for the US keyboard layout */
183 static unsigned short standard_key_capslock_table[KEY_MAX] =
184 {
185 /* start */ 0,
186 /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
187 /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
188 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
189 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
190 /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
191 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
192 /* numpad */ '/', '*', '-', '+', '.', 13,
193 /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0,
194 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
195 };
196
197
198
199 /* shifted mapping table for the US keyboard layout */
200 static unsigned short standard_key_shift_table[KEY_MAX] =
201 {
202 /* start */ 0,
203 /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
204 /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
205 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
206 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
207 /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ',
208 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
209 /* numpad */ '/', '*', '-', '+', '.', 13,
210 /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, '"', 0, 0, 0, 0, 0,
211 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
212 };
213
214
215
216 /* ctrl+key mapping table for the US keyboard layout */
217 static unsigned short standard_key_control_table[KEY_MAX] =
218 {
219 /* start */ 0,
220 /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
221 /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
222 /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
223 /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
224 /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
225 /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
226 /* numpad */ 2, 2, 2, 2, 2, 10,
227 /* others */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
229 };
230
231
232
233 /* empty table for stuff we don't need (accents in US map) */
234 static unsigned short standard_key_empty_table[KEY_MAX];
235
236
237
238 /* alternative mappings for custom keyboard layouts */
239 static unsigned short custom_key_ascii_table[KEY_MAX];
240 static unsigned short custom_key_capslock_table[KEY_MAX];
241 static unsigned short custom_key_shift_table[KEY_MAX];
242 static unsigned short custom_key_control_table[KEY_MAX];
243 static unsigned short custom_key_altgr_lower_table[KEY_MAX];
244 static unsigned short custom_key_altgr_upper_table[KEY_MAX];
245 static unsigned short custom_key_accent1_lower_table[KEY_MAX];
246 static unsigned short custom_key_accent1_upper_table[KEY_MAX];
247 static unsigned short custom_key_accent2_lower_table[KEY_MAX];
248 static unsigned short custom_key_accent2_upper_table[KEY_MAX];
249 static unsigned short custom_key_accent3_lower_table[KEY_MAX];
250 static unsigned short custom_key_accent3_upper_table[KEY_MAX];
251 static unsigned short custom_key_accent4_lower_table[KEY_MAX];
252 static unsigned short custom_key_accent4_upper_table[KEY_MAX];
253
254
255 /* shortcut pointers to the current layout mappings */
256 unsigned short *_key_ascii_table = standard_key_ascii_table;
257 unsigned short *_key_capslock_table = standard_key_capslock_table;
258 unsigned short *_key_shift_table = standard_key_shift_table;
259 unsigned short *_key_control_table = standard_key_control_table;
260 unsigned short *_key_altgr_lower_table = standard_key_empty_table;
261 unsigned short *_key_altgr_upper_table = standard_key_empty_table;
262 unsigned short *_key_accent1_lower_table = standard_key_empty_table;
263 unsigned short *_key_accent1_upper_table = standard_key_empty_table;
264 unsigned short *_key_accent2_lower_table = standard_key_empty_table;
265 unsigned short *_key_accent2_upper_table = standard_key_empty_table;
266 unsigned short *_key_accent3_lower_table = standard_key_empty_table;
267 unsigned short *_key_accent3_upper_table = standard_key_empty_table;
268 unsigned short *_key_accent4_lower_table = standard_key_empty_table;
269 unsigned short *_key_accent4_upper_table = standard_key_empty_table;
270
271
272
273 /* Table with key descriptions. */
274 char *_pckeys_names[KEY_MAX];
275
276
277
278 /* set_standard_keyboard:
279 * Sets up pointers ready to use the standard US keyboard mapping.
280 */
set_standard_keyboard(void)281 static INLINE void set_standard_keyboard(void)
282 {
283 _key_ascii_table = standard_key_ascii_table;
284 _key_capslock_table = standard_key_capslock_table;
285 _key_shift_table = standard_key_shift_table;
286 _key_control_table = standard_key_control_table;
287 _key_altgr_lower_table = standard_key_empty_table;
288 _key_altgr_upper_table = standard_key_empty_table;
289 _key_accent1_lower_table = standard_key_empty_table;
290 _key_accent1_upper_table = standard_key_empty_table;
291 _key_accent2_lower_table = standard_key_empty_table;
292 _key_accent2_upper_table = standard_key_empty_table;
293 _key_accent3_lower_table = standard_key_empty_table;
294 _key_accent3_upper_table = standard_key_empty_table;
295 _key_accent4_lower_table = standard_key_empty_table;
296 _key_accent4_upper_table = standard_key_empty_table;
297
298 _key_standard_kb = TRUE;
299 }
300
301
302
303 /* set_custom_keyboard:
304 * Sets up pointers ready to use the custom keyboard mapping.
305 */
set_custom_keyboard(void)306 static INLINE void set_custom_keyboard(void)
307 {
308 _key_ascii_table = custom_key_ascii_table;
309 _key_capslock_table = custom_key_capslock_table;
310 _key_shift_table = custom_key_shift_table;
311 _key_control_table = custom_key_control_table;
312 _key_altgr_lower_table = custom_key_altgr_lower_table;
313 _key_altgr_upper_table = custom_key_altgr_upper_table;
314 _key_accent1_lower_table = custom_key_accent1_lower_table;
315 _key_accent1_upper_table = custom_key_accent1_upper_table;
316 _key_accent2_lower_table = custom_key_accent2_lower_table;
317 _key_accent2_upper_table = custom_key_accent2_upper_table;
318 _key_accent3_lower_table = custom_key_accent3_lower_table;
319 _key_accent3_upper_table = custom_key_accent3_upper_table;
320 _key_accent4_lower_table = custom_key_accent4_lower_table;
321 _key_accent4_upper_table = custom_key_accent4_upper_table;
322
323 _key_standard_kb = FALSE;
324 }
325
326
327
328 /* _pckey_scancode_to_ascii:
329 * Looks up a scancode in the current mapping table.
330 */
_pckey_scancode_to_ascii(int scancode)331 int _pckey_scancode_to_ascii(int scancode)
332 {
333 int val;
334
335 if ((scancode < 0) || (scancode >= KEY_MAX))
336 return 0;
337
338 val = _key_ascii_table[scancode];
339
340 if (val == 0xFFFF)
341 val = 0;
342
343 return val;
344 }
345
346
347
348 /* _pckey_scancode_to_name:
349 * Like above, but returns a static string and also works for things like
350 * modifier keys.
351 */
_pckey_scancode_to_name(int scancode)352 AL_CONST char *_pckey_scancode_to_name(int scancode)
353 {
354 if ((scancode < 0) || (scancode >= KEY_MAX))
355 return NULL;
356
357 return _pckeys_names[scancode];
358 }
359
360
361
362 /* _handle_pckey:
363 * Handles PC keyboard input, in the same format it comes from the
364 * keyboard controller hardware (raw scancodes, top bit set means the
365 * key was released, special escapes for extended keys, pause, etc).
366 * This routine translates the data using the current mapping table,
367 * and calls routines from keyboard.c as required.
368 */
_handle_pckey(int code)369 void _handle_pckey(int code)
370 {
371 int origcode, mycode, flag, numflag, i=0;
372 unsigned short *table;
373
374 if (key_pause_loop) {
375 /* skip multiple codes generated by the pause key */
376 key_pause_loop--;
377 return;
378 }
379
380 if (code == 0xE1) {
381 /* the pause key requires special handling */
382 if (key_paused)
383 _handle_key_release(KEY_PAUSE);
384 else
385 _handle_key_press(0, KEY_PAUSE);
386
387 key_paused = !key_paused;
388 key_pause_loop = 5;
389 return;
390 }
391
392 if (code == 0xE0) {
393 /* flag that the next key will be an extended one */
394 key_extended = TRUE;
395 return;
396 }
397
398 /* convert from hardware to Allegro format */
399 if (key_extended) {
400 mycode = hw_to_mycode_ex[code & 0x7F];
401 key_extended = FALSE;
402 }
403 else
404 mycode = hw_to_mycode[code & 0x7F];
405
406 if (!mycode)
407 return;
408
409 origcode = mycode;
410
411 if (mycode >= KEY_MODIFIERS)
412 flag = modifier_table[mycode - KEY_MODIFIERS];
413 else
414 flag = 0;
415
416 numflag = ((_key_shifts & KB_NUMLOCK_FLAG) != 0) == ((_key_shifts & KB_SHIFT_FLAG) != 0);
417
418 /* handle released keys */
419 if (code & 0x80) {
420 if (flag & KB_ALT_FLAG) {
421 /* end of an alt+numpad numeric entry sequence */
422 if (_key_shifts & KB_INALTSEQ_FLAG) {
423 _key_shifts &= ~KB_INALTSEQ_FLAG;
424 _handle_key_press(key_pad_seq, 0);
425 }
426 }
427
428 if (flag & KB_MODIFIERS) {
429 /* turn off the shift state for this key */
430 _key_shifts &= ~flag;
431 if (mycode == KEY_ALTGR)
432 key_altgr = FALSE;
433 }
434
435 /* update the key array for a released key */
436 _handle_key_release(mycode);
437 return;
438 }
439
440 if ((mycode == KEY_F1) && ((_key_shifts & KB_CTRL_ALT) == KB_CTRL_ALT)) {
441 /* switch to the standard keyboard layout */
442 _handle_key_press(-1, KEY_F1);
443 set_standard_keyboard();
444 return;
445 }
446
447 if ((mycode == KEY_F2) && ((_key_shifts & KB_CTRL_ALT) == KB_CTRL_ALT)) {
448 /* switch to the custom keyboard layout */
449 _handle_key_press(-1, KEY_F2);
450 set_custom_keyboard();
451 return;
452 }
453
454 if (flag & KB_MODIFIERS) {
455 /* turn on a modifier key */
456 _key_shifts |= flag;
457 if (mycode == KEY_ALTGR)
458 key_altgr = TRUE;
459 _handle_key_press(-1, origcode);
460 return;
461 }
462
463 if ((flag & KB_LED_FLAGS) && (key_led_flag)) {
464 /* toggle caps/num/scroll lock */
465 _key_shifts ^= flag;
466 _handle_key_press(-1, origcode);
467 return;
468 }
469
470 /* new ACCENT stuff */
471 if (!_key_standard_kb) {
472 if ((mycode == _key_accent1) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent1_flag)) {
473 _key_shifts |= KB_ACCENT1_FLAG;
474 _handle_key_press(-1, origcode);
475 return;
476 }
477 else if ((mycode == _key_accent2) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent2_flag)) {
478 _key_shifts |= KB_ACCENT2_FLAG;
479 _handle_key_press(-1, origcode);
480 return;
481 }
482 else if ((mycode == _key_accent3) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent3_flag)) {
483 _key_shifts |= KB_ACCENT3_FLAG;
484 _handle_key_press(-1, origcode);
485 return;
486 }
487 else if ((mycode == _key_accent4) && ((_key_shifts & KB_SH_CTRL_ALT) == _key_accent4_flag)) {
488 _key_shifts |= KB_ACCENT4_FLAG;
489 _handle_key_press(-1, origcode);
490 return;
491 }
492 }
493
494 if (_key_shifts & KB_ACCENTS) {
495 /* accented character input */
496 if (((_key_shifts & KB_SHIFT_FLAG) != 0) ^ ((_key_shifts & KB_CAPSLOCK_FLAG) != 0)) {
497 if (_key_shifts & KB_ACCENT1_FLAG)
498 table = _key_accent1_upper_table;
499 else if (_key_shifts & KB_ACCENT2_FLAG)
500 table = _key_accent2_upper_table;
501 else if (_key_shifts & KB_ACCENT3_FLAG)
502 table = _key_accent3_upper_table;
503 else if (_key_shifts & KB_ACCENT4_FLAG)
504 table = _key_accent4_upper_table;
505 else
506 table = NULL;
507 }
508 else {
509 if (_key_shifts & KB_ACCENT1_FLAG)
510 table = _key_accent1_lower_table;
511 else if (_key_shifts & KB_ACCENT2_FLAG)
512 table = _key_accent2_lower_table;
513 else if (_key_shifts & KB_ACCENT3_FLAG)
514 table = _key_accent3_lower_table;
515 else if (_key_shifts & KB_ACCENT4_FLAG)
516 table = _key_accent4_lower_table;
517 else
518 table = NULL;
519 }
520
521 if (table[mycode]) {
522 /* simple accented char */
523 _key_shifts &= ~KB_ACCENTS;
524 _handle_key_press(table[mycode], origcode);
525 return;
526 }
527 else {
528 /* add the accent as an individual character */
529 if (_key_shifts & (KB_ACCENT1_FLAG)) i = _key_accent1;
530 else if (_key_shifts & (KB_ACCENT2_FLAG)) i = _key_accent2;
531 else if (_key_shifts & (KB_ACCENT3_FLAG)) i = _key_accent3;
532 else if (_key_shifts & (KB_ACCENT4_FLAG)) i = _key_accent4;
533
534 _handle_key_press(_key_ascii_table[i], i);
535 _key_shifts &= ~KB_ACCENTS;
536 }
537 }
538
539 if (_key_shifts & KB_ALT_FLAG) {
540 if ((mycode >= KEY_0_PAD) && (mycode <= KEY_9_PAD)) {
541 /* alt+numpad numeric entry */
542 if (_key_shifts & KB_INALTSEQ_FLAG) {
543 key_pad_seq = key_pad_seq*10 + mycode - KEY_0_PAD;
544 }
545 else {
546 _key_shifts |= KB_INALTSEQ_FLAG;
547 key_pad_seq = mycode - KEY_0_PAD;
548 }
549 _handle_key_press(-1, origcode);
550 return;
551 }
552 else {
553 /* alt+key */
554 if (_key_ascii_table[mycode] == 0xFFFF)
555 i = 0xFFFF;
556 else if (key_altgr) {
557 if (((_key_shifts & KB_SHIFT_FLAG) != 0) ^ ((_key_shifts & KB_CAPSLOCK_FLAG) != 0))
558 i = _key_altgr_upper_table[mycode];
559 else
560 i = _key_altgr_lower_table[mycode];
561 }
562 else
563 i = 0;
564 }
565 }
566 else if ((mycode >= KEY_0_PAD) && (mycode <= KEY_9_PAD)) {
567 /* handle numlock number->arrow conversions */
568 i = mycode - KEY_0_PAD;
569 if ((_key_shifts & KB_CTRL_FLAG) || (numflag)) {
570 mycode = numlock_table[i];
571 i = 0xFFFF;
572 }
573 else
574 i = _key_ascii_table[mycode];
575 }
576 else if (mycode == KEY_DEL_PAD) {
577 /* handle numlock logic for the del key */
578 if (numflag) {
579 mycode = KEY_DEL;
580 i = 0xFFFF;
581 }
582 else
583 i = _key_ascii_table[KEY_DEL_PAD];
584 }
585 else if (_key_shifts & KB_CTRL_FLAG) {
586 /* ctrl+key */
587 i = _key_control_table[mycode];
588 }
589 else if (_key_shifts & KB_SHIFT_FLAG) {
590 /* shift+key */
591 if (_key_shifts & KB_CAPSLOCK_FLAG) {
592 if (_key_ascii_table[mycode] == _key_capslock_table[mycode])
593 i = _key_shift_table[mycode];
594 else
595 i = _key_ascii_table[mycode];
596 }
597 else
598 i = _key_shift_table[mycode];
599 }
600 else if (_key_shifts & KB_CAPSLOCK_FLAG) {
601 /* capslock+key */
602 i = _key_capslock_table[mycode];
603 }
604 else {
605 /* normal key */
606 i = _key_ascii_table[mycode];
607 }
608
609 /* use the current modifier state in place of the key code? */
610 if (i == 0xFFFF)
611 i = _key_shifts & KB_MODIFIERS;
612
613 _key_shifts &= ~KB_INALTSEQ_FLAG;
614
615 /* phew! */
616 _handle_key_press(i, origcode);
617 }
618
619 END_OF_FUNCTION(_handle_pckey);
620
621
622
623 /* read_key_table:
624 * Reads a specific keymapping table from the config file.
625 */
read_key_table(unsigned short * out,unsigned short * in,char * section)626 static void read_key_table(unsigned short *out, unsigned short *in, char *section)
627 {
628 char tmp1[64], tmp2[128], name[128];
629 char *fmt = uconvert_ascii("key%d", tmp1);
630 char *sec = uconvert_ascii(section, tmp2);
631 int i;
632
633 for (i=0; i<KEY_MAX; i++) {
634 uszprintf(name, sizeof(name), fmt, i);
635 out[i] = get_config_int(sec, name, in[i]);
636 }
637 }
638
639
640
641 /* Updates the key descriptions from the ASCII values. */
update_key_descriptions(void)642 static void update_key_descriptions(void)
643 {
644 char str[64];
645 int i;
646 for (i = 0; i < KEY_MAX; i++)
647 {
648 int ascii = scancode_to_ascii (i);
649 if (_pckeys_names[i])
650 _AL_FREE(_pckeys_names[i]);
651 if (ascii > ' ') {
652 uszprintf(str, sizeof str, "%c", ascii);
653 _pckeys_names[i] = strdup (str);
654 }
655 else {
656 _pckeys_names[i] = strdup(_keyboard_common_names[i]);
657 }
658 }
659 }
660
661
662
663 /* read_keyboard_config:
664 * Reads in the keyboard config tables.
665 */
read_keyboard_config(void)666 static void read_keyboard_config(void)
667 {
668 char filename[1024], tmp1[128], tmp2[128], *ext, *datafile;
669 AL_CONST char* name;
670
671 name = get_config_string(uconvert_ascii("system", tmp1), uconvert_ascii("keyboard", tmp2), _keyboard_layout);
672
673 if ((!name) || (!ugetc(name)))
674 return;
675
676 ext = uconvert_ascii(".cfg", tmp1);
677 datafile = uconvert_ascii("keyboard.dat", tmp2);
678
679 if (find_allegro_resource(filename, name, ext, datafile, NULL, NULL, NULL, sizeof(filename)) != 0)
680 return;
681
682 push_config_state();
683 set_config_file(filename);
684
685 read_key_table(custom_key_ascii_table, standard_key_ascii_table, "key_ascii");
686 read_key_table(custom_key_capslock_table, standard_key_capslock_table, "key_capslock");
687 read_key_table(custom_key_shift_table, standard_key_shift_table, "key_shift");
688 read_key_table(custom_key_control_table, standard_key_control_table, "key_control");
689
690 /* preserve backward compatibility with former unique key_altgr table */
691 read_key_table(custom_key_altgr_lower_table, standard_key_empty_table, "key_altgr");
692 read_key_table(custom_key_altgr_upper_table, standard_key_empty_table, "key_altgr");
693
694 read_key_table(custom_key_altgr_lower_table, custom_key_altgr_lower_table, "key_altgr_lower");
695 read_key_table(custom_key_altgr_upper_table, custom_key_altgr_upper_table, "key_altgr_upper");
696
697 read_key_table(custom_key_accent1_lower_table, standard_key_empty_table, "key_accent1_lower");
698 read_key_table(custom_key_accent1_upper_table, standard_key_empty_table, "key_accent1_upper");
699 read_key_table(custom_key_accent2_lower_table, standard_key_empty_table, "key_accent2_lower");
700 read_key_table(custom_key_accent2_upper_table, standard_key_empty_table, "key_accent2_upper");
701 read_key_table(custom_key_accent3_lower_table, standard_key_empty_table, "key_accent3_lower");
702 read_key_table(custom_key_accent3_upper_table, standard_key_empty_table, "key_accent3_upper");
703 read_key_table(custom_key_accent4_lower_table, standard_key_empty_table, "key_accent4_lower");
704 read_key_table(custom_key_accent4_upper_table, standard_key_empty_table, "key_accent4_upper");
705
706 _key_accent1 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent1", tmp2), 0);
707 _key_accent2 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent2", tmp2), 0);
708 _key_accent3 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent3", tmp2), 0);
709 _key_accent4 = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent4", tmp2), 0);
710
711 _key_accent1_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent1_flag", tmp2), 0);
712 _key_accent2_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent2_flag", tmp2), 0);
713 _key_accent3_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent3_flag", tmp2), 0);
714 _key_accent4_flag = get_config_int(uconvert_ascii("key_escape", tmp1), uconvert_ascii("accent4_flag", tmp2), 0);
715
716 pop_config_state();
717
718 set_custom_keyboard();
719
720 update_key_descriptions();
721 }
722
723
724
725 /* _pckeys_init:
726 * Initialises the scancode translation routines, loading mapping tables
727 * from keyboard.dat.
728 */
_pckeys_init(void)729 void _pckeys_init(void)
730 {
731 int i;
732
733 _key_accent1 = 0;
734 _key_accent2 = 0;
735 _key_accent3 = 0;
736 _key_accent4 = 0;
737 _key_accent1_flag = 0;
738 _key_accent2_flag = 0;
739 _key_accent3_flag = 0;
740 _key_accent4_flag = 0;
741
742 key_extended = FALSE;
743 key_altgr = FALSE;
744 key_pad_seq = 0;
745 key_pause_loop = 0;
746 key_paused = FALSE;
747
748 for (i=0; i<KEY_MAX; i++)
749 standard_key_empty_table[i] = 0;
750
751 memcpy(custom_key_ascii_table, standard_key_ascii_table, sizeof(custom_key_ascii_table));
752 memcpy(custom_key_capslock_table, standard_key_capslock_table, sizeof(custom_key_capslock_table));
753 memcpy(custom_key_shift_table, standard_key_shift_table, sizeof(custom_key_shift_table));
754 memcpy(custom_key_control_table, standard_key_control_table, sizeof(custom_key_control_table));
755 memcpy(custom_key_altgr_lower_table, standard_key_empty_table, sizeof(custom_key_altgr_lower_table));
756 memcpy(custom_key_altgr_upper_table, standard_key_empty_table, sizeof(custom_key_altgr_upper_table));
757 memcpy(custom_key_accent1_lower_table, standard_key_empty_table, sizeof(custom_key_accent1_lower_table));
758 memcpy(custom_key_accent1_upper_table, standard_key_empty_table, sizeof(custom_key_accent1_upper_table));
759 memcpy(custom_key_accent2_lower_table, standard_key_empty_table, sizeof(custom_key_accent2_lower_table));
760 memcpy(custom_key_accent2_upper_table, standard_key_empty_table, sizeof(custom_key_accent2_upper_table));
761 memcpy(custom_key_accent3_lower_table, standard_key_empty_table, sizeof(custom_key_accent1_lower_table));
762 memcpy(custom_key_accent3_upper_table, standard_key_empty_table, sizeof(custom_key_accent1_upper_table));
763 memcpy(custom_key_accent4_lower_table, standard_key_empty_table, sizeof(custom_key_accent2_lower_table));
764 memcpy(custom_key_accent4_upper_table, standard_key_empty_table, sizeof(custom_key_accent2_upper_table));
765
766 update_key_descriptions();
767
768 LOCK_VARIABLE(hw_to_mycode);
769 LOCK_VARIABLE(hw_to_mycode_ex);
770 LOCK_VARIABLE(modifier_table);
771 LOCK_VARIABLE(numlock_table);
772 LOCK_VARIABLE(standard_key_ascii_table);
773 LOCK_VARIABLE(standard_key_capslock_table);
774 LOCK_VARIABLE(standard_key_shift_table);
775 LOCK_VARIABLE(standard_key_control_table);
776 LOCK_VARIABLE(standard_key_empty_table);
777 LOCK_VARIABLE(custom_key_ascii_table);
778 LOCK_VARIABLE(custom_key_capslock_table);
779 LOCK_VARIABLE(custom_key_shift_table);
780 LOCK_VARIABLE(custom_key_control_table);
781 LOCK_VARIABLE(custom_key_altgr_lower_table);
782 LOCK_VARIABLE(custom_key_altgr_upper_table);
783 LOCK_VARIABLE(custom_key_accent1_lower_table);
784 LOCK_VARIABLE(custom_key_accent1_upper_table);
785 LOCK_VARIABLE(custom_key_accent2_lower_table);
786 LOCK_VARIABLE(custom_key_accent2_upper_table);
787 LOCK_VARIABLE(custom_key_accent3_lower_table);
788 LOCK_VARIABLE(custom_key_accent3_upper_table);
789 LOCK_VARIABLE(custom_key_accent4_lower_table);
790 LOCK_VARIABLE(custom_key_accent4_upper_table);
791 LOCK_VARIABLE(_key_ascii_table);
792 LOCK_VARIABLE(_key_capslock_table);
793 LOCK_VARIABLE(_key_shift_table);
794 LOCK_VARIABLE(_key_control_table);
795 LOCK_VARIABLE(_key_altgr_lower_table);
796 LOCK_VARIABLE(_key_altgr_upper_table);
797 LOCK_VARIABLE(_key_accent1_lower_table);
798 LOCK_VARIABLE(_key_accent1_upper_table);
799 LOCK_VARIABLE(_key_accent2_lower_table);
800 LOCK_VARIABLE(_key_accent2_upper_table);
801 LOCK_VARIABLE(_key_accent3_lower_table);
802 LOCK_VARIABLE(_key_accent3_upper_table);
803 LOCK_VARIABLE(_key_accent4_lower_table);
804 LOCK_VARIABLE(_key_accent4_upper_table);
805 LOCK_VARIABLE(_key_standard_kb);
806 LOCK_VARIABLE(key_extended);
807 LOCK_VARIABLE(key_altgr);
808 LOCK_VARIABLE(key_pad_seq);
809 LOCK_VARIABLE(key_pause_loop);
810 LOCK_VARIABLE(key_paused);
811 LOCK_VARIABLE(_key_accent1);
812 LOCK_VARIABLE(_key_accent2);
813 LOCK_VARIABLE(_key_accent3);
814 LOCK_VARIABLE(_key_accent4);
815 LOCK_VARIABLE(_key_accent1_flag);
816 LOCK_VARIABLE(_key_accent2_flag);
817 LOCK_VARIABLE(_key_accent3_flag);
818 LOCK_VARIABLE(_key_accent4_flag);
819 LOCK_FUNCTION(_handle_pckey);
820
821 _key_standard_kb = TRUE;
822
823 read_keyboard_config();
824 }
825
826