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