]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/key.c
clean up names
[btb/d2x.git] / arch / sdl / key.c
1 /*
2  *
3  * SDL keyboard input support
4  *
5  *
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <conf.h>
10 #endif
11
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 #include <SDL.h>
16
17 #include "inferno.h"
18 #include "game.h"
19 #include "event.h"
20 #include "error.h"
21 #include "key.h"
22 #include "timer.h"
23 #include "console.h"
24 #include "u_mem.h"
25 #include "mouse.h"
26
27
28 #define KEY_BUFFER_SIZE 16
29
30 static unsigned char Installed = 0;
31
32 //-------- Variable accessed by outside functions ---------
33 unsigned char           keyd_buffer_type; // 0=No buffer, 1=buffer ASCII, 2=buffer scans
34 unsigned char           keyd_repeat;
35 unsigned char           keyd_editor_mode;
36 volatile unsigned char  keyd_last_pressed;
37 volatile unsigned char  keyd_last_released;
38 volatile unsigned char  keyd_pressed[256];
39 volatile int            keyd_time_when_last_pressed;
40
41 typedef struct Key_info {
42         ubyte   state;          // state of key 1 == down, 0 == up
43         ubyte   last_state;     // previous state of key
44         int     counter;        // incremented each time key is down in handler
45         fix     timewentdown;   // simple counter incremented each time in interrupt and key is down
46         fix     timehelddown;   // counter to tell how long key is down -- gets reset to 0 by key routines
47         ubyte   downcount;      // number of key counts key was down
48         ubyte   upcount;        // number of times key was released
49 } Key_info;
50
51 typedef struct keyboard {
52         unsigned short  keybuffer[KEY_BUFFER_SIZE];
53         Key_info        keys[256];
54         fix             time_pressed[KEY_BUFFER_SIZE];
55         unsigned int    keyhead, keytail;
56 } keyboard;
57
58 static keyboard key_data;
59
60 typedef struct key_props {
61         char *key_text;
62         unsigned char ascii_value;
63         unsigned char shifted_ascii_value;
64         SDLKey sym;
65 } key_props;
66
67 key_props key_properties[256] = {
68 { "",       255,    255,    -1                 },
69 { "ESC",    255,    255,    SDLK_ESCAPE        },
70 { "1",      '1',    '!',    SDLK_1             },
71 { "2",      '2',    '@',    SDLK_2             },
72 { "3",      '3',    '#',    SDLK_3             },
73 { "4",      '4',    '$',    SDLK_4             },
74 { "5",      '5',    '%',    SDLK_5             },
75 { "6",      '6',    '^',    SDLK_6             },
76 { "7",      '7',    '&',    SDLK_7             },
77 { "8",      '8',    '*',    SDLK_8             },
78 { "9",      '9',    '(',    SDLK_9             },
79 { "0",      '0',    ')',    SDLK_0             },
80 { "-",      '-',    '_',    SDLK_MINUS         },
81 { "=",      '=',    '+',    SDLK_EQUALS        },
82 { "BSPC",   255,    255,    SDLK_BACKSPACE     },
83 { "TAB",    255,    255,    SDLK_TAB           },
84 { "Q",      'q',    'Q',    SDLK_q             },
85 { "W",      'w',    'W',    SDLK_w             },
86 { "E",      'e',    'E',    SDLK_e             },
87 { "R",      'r',    'R',    SDLK_r             },
88 { "T",      't',    'T',    SDLK_t             },
89 { "Y",      'y',    'Y',    SDLK_y             },
90 { "U",      'u',    'U',    SDLK_u             },
91 { "I",      'i',    'I',    SDLK_i             },
92 { "O",      'o',    'O',    SDLK_o             },
93 { "P",      'p',    'P',    SDLK_p             },
94 { "[",      '[',    '{',    SDLK_LEFTBRACKET   },
95 { "]",      ']',    '}',    SDLK_RIGHTBRACKET  },
96 { "RETURN", 255,    255,    SDLK_RETURN        },
97 { "LCTRL",  255,    255,    SDLK_LCTRL         },
98 { "A",      'a',    'A',    SDLK_a             },
99 { "S",      's',    'S',    SDLK_s             },
100 { "D",      'd',    'D',    SDLK_d             },
101 { "F",      'f',    'F',    SDLK_f             },
102 { "G",      'g',    'G',    SDLK_g             },
103 { "H",      'h',    'H',    SDLK_h             },
104 { "J",      'j',    'J',    SDLK_j             },
105 { "K",      'k',    'K',    SDLK_k             },
106 { "L",      'l',    'L',    SDLK_l             },
107 { ";",      ';',    ':',    SDLK_SEMICOLON     },
108 { "'",     '\'',    '"',    SDLK_QUOTE         },
109 { "`",      '`',    '~',    SDLK_BACKQUOTE     },
110 { "LSHFT",  255,    255,    SDLK_LSHIFT        },
111 { "\\",    '\\',    '|',    SDLK_BACKSLASH     },
112 { "Z",      'z',    'Z',    SDLK_z             },
113 { "X",      'x',    'X',    SDLK_x             },
114 { "C",      'c',    'C',    SDLK_c             },
115 { "V",      'v',    'V',    SDLK_v             },
116 { "B",      'b',    'B',    SDLK_b             },
117 { "N",      'n',    'N',    SDLK_n             },
118 { "M",      'm',    'M',    SDLK_m             },
119 { ",",      ',',    '<',    SDLK_COMMA         },
120 { ".",      '.',    '>',    SDLK_PERIOD        },
121 { "/",      '/',    '?',    SDLK_SLASH         },
122 { "RSHFT",  255,    255,    SDLK_RSHIFT        },
123 { "PAD*",   '*',    255,    SDLK_KP_MULTIPLY   },
124 { "LALT",   255,    255,    SDLK_LALT          },
125 { "SPC",    ' ',    ' ',    SDLK_SPACE         },
126 { "CPSLK",  255,    255,    SDLK_CAPSLOCK      },
127 { "F1",     255,    255,    SDLK_F1            },
128 { "F2",     255,    255,    SDLK_F2            },
129 { "F3",     255,    255,    SDLK_F3            },
130 { "F4",     255,    255,    SDLK_F4            },
131 { "F5",     255,    255,    SDLK_F5            },
132 { "F6",     255,    255,    SDLK_F6            },
133 { "F7",     255,    255,    SDLK_F7            },
134 { "F8",     255,    255,    SDLK_F8            },
135 { "F9",     255,    255,    SDLK_F9            },
136 { "F10",    255,    255,    SDLK_F10           },
137 { "NMLCK",  255,    255,    SDLK_NUMLOCK       },
138 { "SCLK",   255,    255,    SDLK_SCROLLOCK     },
139 { "PAD7",   255,    255,    SDLK_KP7           },
140 { "PAD8",   255,    255,    SDLK_KP8           },
141 { "PAD9",   255,    255,    SDLK_KP9           },
142 { "PAD-",   255,    255,    SDLK_KP_MINUS      },
143 { "PAD4",   255,    255,    SDLK_KP4           },
144 { "PAD5",   255,    255,    SDLK_KP5           },
145 { "PAD6",   255,    255,    SDLK_KP6           },
146 { "PAD+",   255,    255,    SDLK_KP_PLUS       },
147 { "PAD1",   255,    255,    SDLK_KP1           },
148 { "PAD2",   255,    255,    SDLK_KP2           },
149 { "PAD3",   255,    255,    SDLK_KP3           },
150 { "PAD0",   255,    255,    SDLK_KP0           },
151 { "PAD.",   255,    255,    SDLK_KP_PERIOD     },
152 { "",       255,    255,    -1                 },
153 { "",       255,    255,    -1                 },
154 { "",       255,    255,    -1                 },
155 { "F11",    255,    255,    SDLK_F11           },
156 { "F12",    255,    255,    SDLK_F12           },
157 { "F13",    255,    255,    SDLK_F13           },
158 { "F14",    255,    255,    SDLK_F14           },
159 { "F15",    255,    255,    SDLK_F15           },
160 #ifdef __APPLE__
161 { "F16",    255,    255,    0x106A             },
162 { "F17",    255,    255,    0x1040             },
163 { "F18",    255,    255,    0x104F             },
164 { "F19",    255,    255,    0x1050             },
165 #else
166 { "",       255,    255,    -1                 },
167 { "",       255,    255,    -1                 },
168 { "",       255,    255,    -1                 },
169 { "",       255,    255,    -1                 },
170 #endif
171 { "",       255,    255,    -1                 },
172 { "PAUSE",  255,    255,    SDLK_PAUSE         },
173 { "",       255,    255,    -1                 },
174 { "",       255,    255,    -1                 },
175 { "",       255,    255,    -1                 },
176 { "",       255,    255,    -1                 },
177 { "",       255,    255,    -1                 },
178 { "",       255,    255,    -1                 },
179 { "",       255,    255,    -1                 },
180 { "",       255,    255,    -1                 },
181 { "",       255,    255,    -1                 },
182 { "",       255,    255,    -1                 },
183 { "",       255,    255,    -1                 },
184 { "",       255,    255,    -1                 },
185 { "",       255,    255,    -1                 },
186 { "",       255,    255,    -1                 },
187 { "",       255,    255,    -1                 },
188 { "",       255,    255,    -1                 },
189 { "",       255,    255,    -1                 },
190 { "",       255,    255,    -1                 },
191 { "",       255,    255,    -1                 },
192 { "",       255,    255,    -1                 },
193 { "",       255,    255,    -1                 },
194 { "",       255,    255,    -1                 },
195 { "",       255,    255,    -1                 },
196 { "",       255,    255,    -1                 },
197 { "",       255,    255,    -1                 },
198 { "",       255,    255,    -1                 },
199 { "",       255,    255,    -1                 },
200 { "",       255,    255,    -1                 },
201 { "",       255,    255,    -1                 },
202 { "",       255,    255,    -1                 },
203 { "",       255,    255,    -1                 },
204 { "",       255,    255,    -1                 },
205 { "",       255,    255,    -1                 },
206 { "",       255,    255,    -1                 },
207 { "",       255,    255,    -1                 },
208 { "",       255,    255,    -1                 },
209 { "",       255,    255,    -1                 },
210 { "",       255,    255,    -1                 },
211 { "",       255,    255,    -1                 },
212 { "",       255,    255,    -1                 },
213 { "",       255,    255,    -1                 },
214 { "",       255,    255,    -1                 },
215 { "",       255,    255,    -1                 },
216 { "",       255,    255,    -1                 },
217 { "",       255,    255,    -1                 },
218 { "",       255,    255,    -1                 },
219 { "",       255,    255,    -1                 },
220 { "",       255,    255,    -1                 },
221 { "",       255,    255,    -1                 },
222 { "",       255,    255,    -1                 },
223 { "",       255,    255,    -1                 },
224 { "",       255,    255,    -1                 },
225 { "",       255,    255,    -1                 },
226 { "",       255,    255,    -1                 },
227 { "",       255,    255,    -1                 },
228 { "",       255,    255,    -1                 },
229 { "",       255,    255,    -1                 },
230 { "PAD=",   255,    255,    SDLK_KP_EQUALS     },
231 { "ENTER",  255,    255,    SDLK_KP_ENTER      },
232 { "RCTRL",  255,    255,    SDLK_RCTRL         },
233 { "LCMD",   255,    255,    SDLK_LMETA         },
234 { "RCMD",   255,    255,    SDLK_RMETA         },
235 { "",       255,    255,    -1                 },
236 { "",       255,    255,    -1                 },
237 { "",       255,    255,    -1                 },
238 { "",       255,    255,    -1                 },
239 { "",       255,    255,    -1                 },
240 { "",       255,    255,    -1                 },
241 { "",       255,    255,    -1                 },
242 { "",       255,    255,    -1                 },
243 { "",       255,    255,    -1                 },
244 { "",       255,    255,    -1                 },
245 { "",       255,    255,    -1                 },
246 { "",       255,    255,    -1                 },
247 { "",       255,    255,    -1                 },
248 { "",       255,    255,    -1                 },
249 { "",       255,    255,    -1                 },
250 { "",       255,    255,    -1                 },
251 { "",       255,    255,    -1                 },
252 { "",       255,    255,    -1                 },
253 { "",       255,    255,    -1                 },
254 { "",       255,    255,    -1                 },
255 { "",       255,    255,    -1                 },
256 { "PAD/",   255,    255,    SDLK_KP_DIVIDE     },
257 { "",       255,    255,    -1                 },
258 { "PRSCR",  255,    255,    SDLK_PRINT         },
259 { "RALT",   255,    255,    SDLK_RALT          },
260 { "",       255,    255,    -1                 },
261 { "",       255,    255,    -1                 },
262 { "",       255,    255,    -1                 },
263 { "",       255,    255,    -1                 },
264 { "",       255,    255,    -1                 },
265 { "",       255,    255,    -1                 },
266 { "",       255,    255,    -1                 },
267 { "",       255,    255,    -1                 },
268 { "",       255,    255,    -1                 },
269 { "",       255,    255,    -1                 },
270 { "",       255,    255,    -1                 },
271 { "",       255,    255,    -1                 },
272 { "",       255,    255,    -1                 },
273 { "",       255,    255,    -1                 },
274 { "HOME",   255,    255,    SDLK_HOME          },
275 { "UP",     255,    255,    SDLK_UP            },
276 { "PGUP",   255,    255,    SDLK_PAGEUP        },
277 { "",       255,    255,    -1                 },
278 { "LEFT",   255,    255,    SDLK_LEFT          },
279 { "",       255,    255,    -1                 },
280 { "RIGHT",  255,    255,    SDLK_RIGHT         },
281 { "",       255,    255,    -1                 },
282 { "END",    255,    255,    SDLK_END           },
283 { "DOWN",   255,    255,    SDLK_DOWN          },
284 { "PGDN",   255,    255,    SDLK_PAGEDOWN      },
285 { "INS",    255,    255,    SDLK_INSERT        },
286 { "DEL",    255,    255,    SDLK_DELETE        },
287 { "",       255,    255,    -1                 },
288 { "",       255,    255,    -1                 },
289 { "",       255,    255,    -1                 },
290 { "",       255,    255,    -1                 },
291 { "",       255,    255,    -1                 },
292 { "",       255,    255,    -1                 },
293 { "",       255,    255,    -1                 },
294 { "",       255,    255,    -1                 },
295 { "",       255,    255,    -1                 },
296 { "",       255,    255,    -1                 },
297 { "",       255,    255,    -1                 },
298 { "",       255,    255,    -1                 },
299 { "",       255,    255,    -1                 },
300 { "",       255,    255,    -1                 },
301 { "",       255,    255,    -1                 },
302 { "",       255,    255,    -1                 },
303 { "",       255,    255,    -1                 },
304 { "",       255,    255,    -1                 },
305 { "",       255,    255,    -1                 },
306 { "",       255,    255,    -1                 },
307 { "",       255,    255,    -1                 },
308 { "",       255,    255,    -1                 },
309 { "",       255,    255,    -1                 },
310 { "",       255,    255,    -1                 },
311 { "",       255,    255,    -1                 },
312 { "",       255,    255,    -1                 },
313 { "",       255,    255,    -1                 },
314 { "",       255,    255,    -1                 },
315 { "",       255,    255,    -1                 },
316 { "",       255,    255,    -1                 },
317 { "",       255,    255,    -1                 },
318 { "",       255,    255,    -1                 },
319 { "",       255,    255,    -1                 },
320 { "",       255,    255,    -1                 },
321 { "",       255,    255,    -1                 },
322 { "",       255,    255,    -1                 },
323 { "",       255,    255,    -1                 },
324 { "",       255,    255,    -1                 },
325 { "",       255,    255,    -1                 },
326 { "",       255,    255,    -1                 },
327 { "",       255,    255,    -1                 },
328 { "",       255,    255,    -1                 },
329 { "",       255,    255,    -1                 },
330 { "",       255,    255,    -1                 },
331 };
332
333 char *key_text[256];
334
335
336 unsigned char key_to_ascii(int keycode )
337 {
338         int shifted;
339
340         shifted = keycode & KEY_SHIFTED;
341         keycode &= 0xFF;
342
343         if (shifted)
344                 return key_properties[keycode].shifted_ascii_value;
345         else
346                 return key_properties[keycode].ascii_value;
347 }
348
349
350 /* The list of keybindings */
351 static char *key_binding_list[256];
352
353
354 /* get the action bound to a key, if any */
355 char *key_binding(ubyte keycode)
356 {
357         return key_binding_list[keycode];
358 }
359
360
361 ubyte key_find_binding(char *text)
362 {
363         int i;
364
365         for (i = 0; i < 256; i++)
366                 if (key_binding_list[i] && !strncasecmp(key_binding_list[i], text, CMD_MAX_LENGTH))
367                         return i;
368
369         return 0;
370 }
371
372
373 /* Write key bindings to file */
374 void key_write_bindings(CFILE *file)
375 {
376         int i;
377
378         for (i = 0; i < 256; i++)
379                 if (key_binding_list[i])
380                         PHYSFSX_printf(file, "bind \"%s\" \"%s\"\n", key_text[i], key_binding_list[i]);
381 }
382
383
384 /* bind */
385 void key_cmd_bind(int argc, char **argv)
386 {
387         char buf[CMD_MAX_LENGTH] = "";
388         int key = -1;
389         int i;
390
391         if (argc == 2 && !stricmp(argv[1], "-h")) {
392                 con_printf(CON_NORMAL, "%s <key> <commands>\n", argv[0]);
393                 con_printf(CON_NORMAL, "    bind <commands> to <key>\n");
394                 con_printf(CON_NORMAL, "%s <key>\n", argv[0]);
395                 con_printf(CON_NORMAL, "    show the current binding for <key>\n");
396                 con_printf(CON_NORMAL, "%s\n", argv[0]);
397                 con_printf(CON_NORMAL, "    show all key bindings\n");
398                 return;
399         }
400
401         if (argc < 2)
402         {
403                 con_printf(CON_NORMAL, "key bindings:\n");
404                 for (i = 0; i < 256; i++) {
405                         if (!key_binding_list[i])
406                                 continue;
407                         con_printf(CON_NORMAL, "%s: %s\n", key_text[i], key_binding_list[i]);
408                 }
409                 return;
410         }
411
412         for (i = 0; i < 256; i++) {
413                 if (!stricmp(argv[1], key_text[i])) {
414                         key = i;
415                         break;
416                 }
417         }
418
419         if (key < 0) {
420                 con_printf(CON_CRITICAL, "bind: key %s not found\n", argv[1]);
421                 return;
422         }
423
424         if (argc < 3) {
425                 if (key_binding_list[key])
426                         con_printf(CON_NORMAL, "%s: %s\n", key_text[key], key_binding_list[key]);
427                 else
428                         con_printf(CON_NORMAL, "%s is unbound\n", key_text[key]);
429                 return;
430         }
431
432         for (i = 2; i < argc; i++) {
433                 if (i > 2)
434                         strncat(buf, " ", CMD_MAX_LENGTH);
435                 strncat(buf, argv[i], CMD_MAX_LENGTH);
436         }
437
438         if (key_binding_list[key])
439                 d_free(key_binding_list[key]);
440         key_binding_list[key] = d_strdup(buf);
441 }
442
443
444 /* unbind */
445 void key_cmd_unbind(int argc, char **argv)
446 {
447         unsigned int key;
448
449         if (argc != 2 || !stricmp(argv[1], "-h")) {
450                 con_printf(CON_NORMAL, "%s <key>\n", argv[0]);
451                 con_printf(CON_NORMAL, "    remove binding from <key>\n");
452                 return;
453         }
454
455         for (key = 0; key < 256; key++) {
456                 if (!stricmp(argv[1], key_text[key])) {
457                         break;
458                 }
459         }
460
461         if (key_binding_list[key])
462                 d_free(key_binding_list[key]);
463         key_binding_list[key] = NULL;
464 }
465
466
467 void key_handle_binding(int keycode, int state)
468 {
469         if (!key_binding_list[keycode])
470                 return;
471
472         if (Game_paused)
473                 return;
474
475         if (Function_mode != FMODE_GAME)
476                 return;
477
478         if (con_is_visible())
479                 return;
480
481         if (!state && key_binding_list[keycode][0] == '+')
482                 cmd_appendf("-%s", &key_binding_list[keycode][1]);
483         else if (state)
484                 cmd_append(key_binding_list[keycode]);
485 }
486
487
488 void key_handler(SDL_KeyboardEvent *event)
489 {
490         int i, event_key, key_state;
491
492         if (event->keysym.sym != SDLK_UNKNOWN)
493                 event_key = event->keysym.sym;
494         else
495                 event_key = 0x1000 | event->keysym.scancode; // hardware scancode, definitions in #ifdefs above
496
497         key_state = (event->state == SDL_PRESSED);
498         //=====================================================
499         //Here a translation from win keycodes to mac keycodes!
500         //=====================================================
501
502         for (i = 255; i >= 0; i--) {
503                 if (key_properties[i].sym == event_key) {
504                         vkey_handler(i, key_state);
505                 }
506         }
507 }
508
509
510 void vkey_handler(int keycode, int state)
511 {
512         unsigned char temp;
513         Key_info *key;
514
515         key = &(key_data.keys[keycode]);
516
517         if (state) {
518                 // Key going down
519                 keyd_last_pressed = keycode;
520                 keyd_time_when_last_pressed = timer_get_fixed_seconds();
521
522                 if (!keyd_pressed[keycode]) {
523                         // First time down
524                         key_handle_binding(keycode, 1);
525                         keyd_pressed[keycode] = 1;
526                         key->downcount += state;
527                         key->state = 1;
528                         key->timewentdown = keyd_time_when_last_pressed;
529                         key->counter++;
530                 }
531         } else {
532                 // Key going up
533                 key_handle_binding(keycode, 0);
534                 keyd_pressed[keycode] = 0;
535                 keyd_last_released = keycode;
536                 key->upcount += key->state;
537                 key->state = 0;
538                 key->counter = 0;
539                 key->timehelddown += timer_get_fixed_seconds() - key->timewentdown;
540         }
541
542         if ( (state && !key->last_state) || (keyd_repeat && state && key->last_state) ) {
543                 if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT])
544                         keycode |= KEY_SHIFTED;
545                 if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT])
546                         keycode |= KEY_ALTED;
547                 if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL])
548                         keycode |= KEY_CTRLED;
549                 if ( keyd_pressed[KEY_LMETA] || keyd_pressed[KEY_RMETA])
550                         keycode |= KEY_METAED;
551                 if ( keyd_pressed[KEY_DELETE] )
552                         keycode |= KEY_DEBUGGED;
553
554                 temp = key_data.keytail + 1;
555                 if ( temp >= KEY_BUFFER_SIZE ) temp=0;
556                 if (temp!=key_data.keyhead)     {
557                         key_data.keybuffer[key_data.keytail] = keycode;
558                         key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed;
559                         key_data.keytail = temp;
560                 }
561         }
562         key->last_state = state;
563 }
564
565
566 void key_close()
567 {
568         int i;
569
570         for (i = 0; i < 256; i++)
571                 if (key_binding_list[i])
572                         d_free(key_binding_list[i]);
573
574         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
575                 d_free(key_text[KEY_MB1 + i]);
576         }
577
578         Installed = 0;
579 }
580
581 void key_init()
582 {
583         int i;
584
585         if (Installed) return;
586
587         Installed=1;
588
589         keyd_time_when_last_pressed = timer_get_fixed_seconds();
590         keyd_buffer_type = 1;
591         keyd_repeat = 1;
592
593         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
594
595         for(i=0; i<256; i++)
596                 key_text[i] = key_properties[i].key_text;
597
598         for (i = 0; i < MOUSE_MAX_BUTTONS; i++) {
599                 char temp[10];
600                 sprintf(temp, "MB%d", i + 1);
601                 key_text[KEY_MB1 + i] = d_strdup(temp);
602         }
603
604         cmd_addcommand("bind", key_cmd_bind);
605         cmd_addcommand("unbind", key_cmd_unbind);
606
607         // Clear the keyboard array
608         key_flush();
609         atexit(key_close);
610 }
611
612 void key_flush()
613 {
614         int i;
615         fix curtime;
616
617         if (!Installed)
618                 key_init();
619
620         key_data.keyhead = key_data.keytail = 0;
621
622         //Clear the keyboard buffer
623         for (i=0; i<KEY_BUFFER_SIZE; i++ ) {
624                 key_data.keybuffer[i] = 0;
625                 key_data.time_pressed[i] = 0;
626         }
627
628 //use gettimeofday here:
629         curtime = timer_get_fixed_seconds();
630
631         for (i=0; i<256; i++) {
632                 keyd_pressed[i] = 0;
633                 key_data.keys[i].state = 1;
634                 key_data.keys[i].last_state = 0;
635                 key_data.keys[i].timewentdown = curtime;
636                 key_data.keys[i].downcount = 0;
637                 key_data.keys[i].upcount = 0;
638                 key_data.keys[i].timehelddown = 0;
639                 key_data.keys[i].counter = 0;
640         }
641 }
642
643 int add_one(int n)
644 {
645         n++;
646         if ( n >= KEY_BUFFER_SIZE ) n = 0;
647
648         return n;
649 }
650
651 int key_checkch()
652 {
653         int is_one_waiting = 0;
654
655         event_poll();
656         if (key_data.keytail != key_data.keyhead)
657                 is_one_waiting = 1;
658
659         return is_one_waiting;
660 }
661
662 int key_inkey()
663 {
664         int key = 0;
665
666         if (!Installed)
667                 key_init();
668
669         event_poll();
670         if (key_data.keytail!=key_data.keyhead) {
671                 key = key_data.keybuffer[key_data.keyhead];
672                 key_data.keyhead = add_one(key_data.keyhead);
673         }
674         else
675                 timer_delay(1);
676
677         return key;
678 }
679
680 int key_inkey_time(fix * time)
681 {
682         int key = 0;
683
684         if (!Installed)
685                 key_init();
686
687         event_poll();
688         if (key_data.keytail != key_data.keyhead) {
689                 key = key_data.keybuffer[key_data.keyhead];
690                 *time = key_data.time_pressed[key_data.keyhead];
691                 key_data.keyhead = add_one(key_data.keyhead);
692         }
693
694         return key;
695 }
696
697 int key_peekkey()
698 {
699         int key = 0;
700
701         event_poll();
702         if (key_data.keytail != key_data.keyhead)
703                 key = key_data.keybuffer[key_data.keyhead];
704
705         return key;
706 }
707
708 int key_getch()
709 {
710         int dummy = 0;
711
712         if (!Installed)
713                 return 0;
714 //              return getch();
715
716         while (!key_checkch())
717                 dummy++;
718
719         return key_inkey();
720 }
721
722 unsigned int key_get_shift_status()
723 {
724         unsigned int shift_status = 0;
725
726         if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
727                 shift_status |= KEY_SHIFTED;
728
729         if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
730                 shift_status |= KEY_ALTED;
731
732         if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
733                 shift_status |= KEY_CTRLED;
734
735         if ( keyd_pressed[KEY_LMETA] || keyd_pressed[KEY_RMETA] )
736                 shift_status |= KEY_METAED;
737
738 #ifndef NDEBUG
739         if (keyd_pressed[KEY_DELETE])
740                 shift_status |=KEY_DEBUGGED;
741 #endif
742
743         return shift_status;
744 }
745
746 // Returns the number of seconds this key has been down since last call.
747 fix key_down_time(int scancode)
748 {
749         fix time_down, time;
750
751         event_poll();
752         if ((scancode<0) || (scancode>255)) return 0;
753
754         if (!keyd_pressed[scancode]) {
755                 time_down = key_data.keys[scancode].timehelddown;
756                 key_data.keys[scancode].timehelddown = 0;
757         } else {
758                 time = timer_get_fixed_seconds();
759                 time_down = time - key_data.keys[scancode].timewentdown;
760                 key_data.keys[scancode].timewentdown = time;
761         }
762
763         return time_down;
764 }
765
766 unsigned int key_down_count(int scancode)
767 {
768         int n;
769
770         event_poll();
771         if ((scancode<0) || (scancode>255)) return 0;
772
773         n = key_data.keys[scancode].downcount;
774         key_data.keys[scancode].downcount = 0;
775
776         return n;
777 }
778
779 unsigned int key_up_count(int scancode)
780 {
781         int n;
782
783         event_poll();
784         if ((scancode<0) || (scancode>255)) return 0;
785
786         n = key_data.keys[scancode].upcount;
787         key_data.keys[scancode].upcount = 0;
788
789         return n;
790 }