added timer_delay, faster timer_get_fixed_seconds
[btb/d2x.git] / arch / sdl / key.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/sdl/key.c,v $
3  * $Revision: 1.1 $
4  * $Author: bradleyb $
5  * $Date: 2001-10-24 09:25:05 $
6  *
7  * SDL keyboard input support
8  *
9  * $Log: not supported by cvs2svn $
10  * Revision 1.2  2001/01/29 14:03:57  bradleyb
11  * Fixed build, minor fixes
12  *
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #include <conf.h>
17 #endif
18
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <SDL/SDL.h>
23
24 #include "event.h"
25 #include "error.h"
26 #include "key.h"
27 #include "timer.h"
28
29 //added on 9/3/98 by Matt Mueller to free some cpu instead of hogging during menus and such
30 #include "d_delay.h"
31 //end this section addition - Matt Mueller
32
33 #define KEY_BUFFER_SIZE 16
34
35 static unsigned char Installed = 0;
36
37 //-------- Variable accessed by outside functions ---------
38 unsigned char           keyd_buffer_type;               // 0=No buffer, 1=buffer ASCII, 2=buffer scans
39 unsigned char           keyd_repeat;
40 unsigned char           keyd_editor_mode;
41 volatile unsigned char  keyd_last_pressed;
42 volatile unsigned char  keyd_last_released;
43 volatile unsigned char  keyd_pressed[256];
44 volatile int            keyd_time_when_last_pressed;
45
46 typedef struct Key_info {
47         ubyte           state;                  // state of key 1 == down, 0 == up
48         ubyte           last_state;             // previous state of key
49         int             counter;                // incremented each time key is down in handler
50         fix             timewentdown;   // simple counter incremented each time in interrupt and key is down
51         fix             timehelddown;   // counter to tell how long key is down -- gets reset to 0 by key routines
52         ubyte           downcount;              // number of key counts key was down
53         ubyte           upcount;                // number of times key was released
54 } Key_info;
55
56 typedef struct keyboard {
57         unsigned short          keybuffer[KEY_BUFFER_SIZE];
58         Key_info                keys[256];
59         fix                     time_pressed[KEY_BUFFER_SIZE];
60         unsigned int            keyhead, keytail;
61 } keyboard;
62
63 static keyboard key_data;
64
65 typedef struct key_props {
66         char *key_text;
67         unsigned char ascii_value;
68         unsigned char shifted_ascii_value;
69         SDLKey sym;
70 } key_props;
71
72 key_props key_properties[256] = {
73 { "",       255,    255,    -1                 },
74 { "ESC",    255,    255,    SDLK_ESCAPE        },
75 { "1",      '1',    '!',    SDLK_1             },
76 { "2",      '2',    '@',    SDLK_2             },
77 { "3",      '3',    '#',    SDLK_3             },
78 { "4",      '4',    '$',    SDLK_4             },
79 { "5",      '5',    '%',    SDLK_5             },
80 { "6",      '6',    '^',    SDLK_6             },
81 { "7",      '7',    '&',    SDLK_7             },
82 { "8",      '8',    '*',    SDLK_8             },
83 { "9",      '9',    '(',    SDLK_9             },
84 { "0",      '0',    ')',    SDLK_0             },
85 { "-",      '-',    '_',    SDLK_MINUS         },
86 { "=",      '=',    '+',    SDLK_EQUALS        },
87 { "BSPC",   255,    255,    SDLK_BACKSPACE     },
88 { "TAB",    255,    255,    SDLK_TAB           },
89 { "Q",      'q',    'Q',    SDLK_q             },
90 { "W",      'w',    'W',    SDLK_w             },
91 { "E",      'e',    'E',    SDLK_e             },
92 { "R",      'r',    'R',    SDLK_r             },
93 { "T",      't',    'T',    SDLK_t             },
94 { "Y",      'y',    'Y',    SDLK_y             },
95 { "U",      'u',    'U',    SDLK_u             },
96 { "I",      'i',    'I',    SDLK_i             },
97 { "O",      'o',    'O',    SDLK_o             },
98 { "P",      'p',    'P',    SDLK_p             },
99 { "[",      '[',    '{',    SDLK_LEFTBRACKET   },
100 { "]",      ']',    '}',    SDLK_RIGHTBRACKET  },
101 //edited 06/08/99 Matt Mueller - set to correct key_text
102 { "\83",      255,    255,    SDLK_RETURN        },
103 //end edit -MM
104 { "LCTRL",  255,    255,    SDLK_LCTRL         },
105 { "A",      'a',    'A',    SDLK_a             },
106 { "S",      's',    'S',    SDLK_s             },
107 { "D",      'd',    'D',    SDLK_d             },
108 { "F",      'f',    'F',    SDLK_f             },
109 { "G",      'g',    'G',    SDLK_g             },
110 { "H",      'h',    'H',    SDLK_h             },
111 { "J",      'j',    'J',    SDLK_j             },
112 { "K",      'k',    'K',    SDLK_k             },
113 { "L",      'l',    'L',    SDLK_l             },
114 //edited 06/08/99 Matt Mueller - set to correct sym
115 { ";",      ';',    ':',    SDLK_SEMICOLON         },
116 //end edit -MM
117 { "'",      '\'',   '"',    SDLK_QUOTE         },
118 //edited 06/08/99 Matt Mueller - set to correct sym
119 { "`",      '`',    '~',    SDLK_BACKQUOTE     },
120 //end edit -MM
121 { "LSHFT",  255,    255,    SDLK_LSHIFT        },
122 { "\\",     '\\',   '|',    SDLK_BACKSLASH     },
123 { "Z",      'z',    'Z',    SDLK_z             },
124 { "X",      'x',    'X',    SDLK_x             },
125 { "C",      'c',    'C',    SDLK_c             },
126 { "V",      'v',    'V',    SDLK_v             },
127 { "B",      'b',    'B',    SDLK_b             },
128 { "N",      'n',    'N',    SDLK_n             },
129 { "M",      'm',    'M',    SDLK_m             },
130 //edited 06/08/99 Matt Mueller - set to correct syms
131 { ",",      ',',    '<',    SDLK_COMMA  },
132 { ".",      '.',    '>',    SDLK_PERIOD },
133 { "/",      '/',    '?',    SDLK_SLASH  },
134 //end edit -MM
135 { "RSHFT",  255,    255,    SDLK_RSHIFT },
136 { "PAD*",   '*',    255,    SDLK_KP_MULTIPLY   },
137 { "LALT",   255,    255,    SDLK_LALT          },
138 { "SPC",    ' ',    ' ',    SDLK_SPACE         },
139 { "CPSLK",  255,    255,    SDLK_CAPSLOCK      },
140 { "F1",     255,    255,    SDLK_F1            },
141 { "F2",     255,    255,    SDLK_F2            },
142 { "F3",     255,    255,    SDLK_F3            },
143 { "F4",     255,    255,    SDLK_F4            },
144 { "F5",     255,    255,    SDLK_F5            },
145 { "F6",     255,    255,    SDLK_F6            },
146 { "F7",     255,    255,    SDLK_F7            },
147 { "F8",     255,    255,    SDLK_F8            },
148 { "F9",     255,    255,    SDLK_F9            },
149 { "F10",    255,    255,    SDLK_F10           },
150 { "NMLCK",  255,    255,    SDLK_NUMLOCK       },
151 { "SCLK",   255,    255,    SDLK_SCROLLOCK     },
152 { "PAD7",   255,    255,    SDLK_KP7           },
153 { "PAD8",   255,    255,    SDLK_KP8           },
154 { "PAD9",   255,    255,    SDLK_KP9           },
155 { "PAD-",   255,    255,    SDLK_KP_MINUS      },
156 { "PAD4",   255,    255,    SDLK_KP4           },
157 { "PAD5",   255,    255,    SDLK_KP5           },
158 { "PAD6",   255,    255,    SDLK_KP6           },
159 { "PAD+",   255,    255,    SDLK_KP_PLUS       },
160 { "PAD1",   255,    255,    SDLK_KP1           },
161 { "PAD2",   255,    255,    SDLK_KP2           },
162 { "PAD3",   255,    255,    SDLK_KP3           },
163 { "PAD0",   255,    255,    SDLK_KP0           },
164 { "PAD.",   255,    255,    SDLK_KP_PERIOD     },
165 { "",       255,    255,    -1                 },
166 { "",       255,    255,    -1                 },
167 { "",       255,    255,    -1                 },
168 { "F11",    255,    255,    SDLK_F11           },
169 { "F12",    255,    255,    SDLK_F12           },
170 { "",       255,    255,    -1                 },       
171 { "",       255,    255,    -1                 },
172 { "",       255,    255,    -1                 },
173 { "",       255,    255,    -1                 },
174 { "",       255,    255,    -1                 },
175 { "",       255,    255,    -1                 },
176 { "",       255,    255,    -1                 },
177 { "",       255,    255,    -1                 },
178 //edited 06/08/99 Matt Mueller - add pause ability
179 { "PAUSE",       255,    255,    SDLK_PAUSE                 },
180 //end edit -MM
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 { "",       255,    255,    -1                 },
231 { "",       255,    255,    -1                 },
232 { "",       255,    255,    -1                 },
233 { "",       255,    255,    -1                 },
234 { "",       255,    255,    -1                 },
235 { "",       255,    255,    -1                 },
236 { "",       255,    255,    -1                 },
237 { "",       255,    255,    -1                 },
238 { "",       255,    255,    -1                 },
239 //edited 06/08/99 Matt Mueller - set to correct key_text
240 { "PAD\83",   255,    255,    SDLK_KP_ENTER      },
241 //end edit -MM
242 //edited 06/08/99 Matt Mueller - set to correct sym
243 { "RCTRL",  255,    255,    SDLK_RCTRL            },
244 //end edit -MM
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 { "",       255,    255,    -1                 },
257 { "",       255,    255,    -1                 },
258 { "",       255,    255,    -1                 },
259 { "",       255,    255,    -1                 },
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 { "PAD/",   255,    255,    SDLK_KP_DIVIDE     },
269 { "",       255,    255,    -1                 },
270 //edited 06/08/99 Matt Mueller - add printscreen ability
271 { "PRSCR",       255,    255,    SDLK_PRINT                 },
272 //end edit -MM
273 { "RALT",   255,    255,    SDLK_RALT          },
274 { "",       255,    255,    -1                 },
275 { "",       255,    255,    -1                 },
276 { "",       255,    255,    -1                 },
277 { "",       255,    255,    -1                 },
278 { "",       255,    255,    -1                 },
279 { "",       255,    255,    -1                 },
280 { "",       255,    255,    -1                 },
281 { "",       255,    255,    -1                 },
282 { "",       255,    255,    -1                 },
283 { "",       255,    255,    -1                 },
284 { "",       255,    255,    -1                 },
285 { "",       255,    255,    -1                 },
286 { "",       255,    255,    -1                 },
287 { "",       255,    255,    -1                 },
288 { "HOME",   255,    255,    SDLK_HOME          },
289 //edited 06/08/99 Matt Mueller - set to correct key_text
290 { "UP",         255,    255,    SDLK_UP            },
291 //end edit -MM
292 { "PGUP",   255,    255,    SDLK_PAGEUP        },
293 { "",       255,    255,    -1                 },
294 //edited 06/08/99 Matt Mueller - set to correct key_text
295 { "LEFT",       255,    255,    SDLK_LEFT          },
296 //end edit -MM
297 { "",       255,    255,    -1                 },
298 //edited 06/08/99 Matt Mueller - set to correct key_text
299 { "RIGHT",      255,    255,    SDLK_RIGHT         },
300 //end edit -MM
301 { "",       255,    255,    -1                 },
302 //edited 06/08/99 Matt Mueller - set to correct key_text
303 { "END",    255,    255,    SDLK_END           },
304 //end edit -MM
305 { "DOWN",       255,    255,    SDLK_DOWN          },
306 { "PGDN",       255,    255,    SDLK_PAGEDOWN      },
307 { "INS",        255,    255,    SDLK_INSERT        },
308 { "DEL",        255,    255,    SDLK_DELETE        },
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 { "",       255,    255,    -1                 },
332 { "",       255,    255,    -1                 },
333 { "",       255,    255,    -1                 },
334 { "",       255,    255,    -1                 },
335 { "",       255,    255,    -1                 },
336 { "",       255,    255,    -1                 },
337 { "",       255,    255,    -1                 },
338 { "",       255,    255,    -1                 },
339 { "",       255,    255,    -1                 },
340 { "",       255,    255,    -1                 },
341 { "",       255,    255,    -1                 },
342 { "",       255,    255,    -1                 },
343 { "",       255,    255,    -1                 },
344 { "",       255,    255,    -1                 },
345 { "",       255,    255,    -1                 },
346 { "",       255,    255,    -1                 },
347 { "",       255,    255,    -1                 },
348 { "",       255,    255,    -1                 },
349 { "",       255,    255,    -1                 },
350 { "",       255,    255,    -1                 },
351 { "",       255,    255,    -1                 },
352 { "",       255,    255,    -1                 },
353 };
354
355 char *key_text[256];
356
357 void key_buid_key_text(void)
358 {
359 }
360
361 unsigned char key_to_ascii(int keycode )
362 {
363         int shifted;
364
365         shifted = keycode & KEY_SHIFTED;
366         keycode &= 0xFF;
367
368         if (shifted)
369                 return key_properties[keycode].shifted_ascii_value;
370         else
371                 return key_properties[keycode].ascii_value;
372 }
373
374 void key_handler(SDL_KeyboardEvent *event)
375 {
376         ubyte state;
377         int i, keycode, event_key, key_state;
378         Key_info *key;
379         unsigned char temp;
380
381         event_key = event->keysym.sym;
382
383         key_state = (event->state == SDL_PRESSED); //  !(wInfo & KF_UP);
384         //=====================================================
385         //Here a translation from win keycodes to mac keycodes!
386         //=====================================================
387
388         for (i = 255; i >= 0; i--) {
389
390                 keycode = i;
391                 key = &(key_data.keys[keycode]);
392                 if (key_properties[i].sym == event_key)
393                         state = key_state;
394                 else
395                         state = key->last_state;
396                         
397                 if ( key->last_state == state ) {
398                         if (state) {
399                                 key->counter++;
400                                 keyd_last_pressed = keycode;
401                                 keyd_time_when_last_pressed = timer_get_fixed_seconds();
402                         }
403                 } else {
404                         if (state)      {
405                                 keyd_last_pressed = keycode;
406                                 keyd_pressed[keycode] = 1;
407                                 key->downcount += state;
408                                 key->state = 1;
409                                 key->timewentdown = keyd_time_when_last_pressed = timer_get_fixed_seconds();
410                                 key->counter++;
411                         } else {        
412                                 keyd_pressed[keycode] = 0;
413                                 keyd_last_released = keycode;
414                                 key->upcount += key->state;
415                                 key->state = 0;
416                                 key->counter = 0;
417                                 key->timehelddown += timer_get_fixed_seconds() - key->timewentdown;
418                         }
419                 }
420                 if ( (state && !key->last_state) || (state && key->last_state && (key->counter > 30) && (key->counter & 0x01)) ) {
421                         if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT])
422                                 keycode |= KEY_SHIFTED;
423                         if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT])
424                                 keycode |= KEY_ALTED;
425                         if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL])
426                                 keycode |= KEY_CTRLED;
427                         if ( keyd_pressed[KEY_DELETE] )
428                                 keycode |= KEY_DEBUGGED;
429                         temp = key_data.keytail+1;
430                         if ( temp >= KEY_BUFFER_SIZE ) temp=0;
431                         if (temp!=key_data.keyhead)     {
432                                 key_data.keybuffer[key_data.keytail] = keycode;
433                                 key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed;
434                                 key_data.keytail = temp;
435                         }
436                 }
437                 key->last_state = state;
438         }
439 }
440
441 void key_close()
442 {
443  Installed = 0;
444 }
445
446 void key_init()
447 {
448   int i;
449   
450   if (Installed) return;
451
452   Installed=1;
453
454   keyd_time_when_last_pressed = timer_get_fixed_seconds();
455   keyd_buffer_type = 1;
456   keyd_repeat = 1;
457   
458   for(i=0; i<256; i++)
459      key_text[i] = key_properties[i].key_text;
460      
461   // Clear the keyboard array
462   key_flush();
463   atexit(key_close);
464 }
465
466 void key_flush()
467 {
468         int i;
469         fix curtime;
470
471         if (!Installed)
472                 key_init();
473
474         key_data.keyhead = key_data.keytail = 0;
475
476         //Clear the keyboard buffer
477         for (i=0; i<KEY_BUFFER_SIZE; i++ )      {
478                 key_data.keybuffer[i] = 0;
479                 key_data.time_pressed[i] = 0;
480         }
481
482 //use gettimeofday here:
483         curtime = timer_get_fixed_seconds();
484
485         for (i=0; i<256; i++ )  {
486                 keyd_pressed[i] = 0;
487                 key_data.keys[i].state = 1;
488                 key_data.keys[i].last_state = 0;
489                 key_data.keys[i].timewentdown = curtime;
490                 key_data.keys[i].downcount=0;
491                 key_data.keys[i].upcount=0;
492                 key_data.keys[i].timehelddown = 0;
493                 key_data.keys[i].counter = 0;
494         }
495 }
496
497 int add_one(int n)
498 {
499  n++;
500  if ( n >= KEY_BUFFER_SIZE ) n=0;
501  return n;
502 }
503
504 int key_checkch()
505 {
506         int is_one_waiting = 0;
507         event_poll();
508         if (key_data.keytail!=key_data.keyhead)
509                 is_one_waiting = 1;
510         return is_one_waiting;
511 }
512
513 int key_inkey()
514 {
515         int key = 0;
516         if (!Installed)
517                 key_init();
518         event_poll();
519         if (key_data.keytail!=key_data.keyhead) {
520                 key = key_data.keybuffer[key_data.keyhead];
521                 key_data.keyhead = add_one(key_data.keyhead);
522         }
523 //added 9/3/98 by Matt Mueller to free cpu time instead of hogging during menus and such
524         else d_delay(1);
525 //end addition - Matt Mueller
526              
527         return key;
528 }
529
530 int key_inkey_time(fix * time)
531 {
532         int key = 0;
533
534         if (!Installed)
535                 key_init();
536         event_poll();
537         if (key_data.keytail!=key_data.keyhead) {
538                 key = key_data.keybuffer[key_data.keyhead];
539                 *time = key_data.time_pressed[key_data.keyhead];
540                 key_data.keyhead = add_one(key_data.keyhead);
541         }
542         return key;
543 }
544
545 int key_peekkey()
546 {
547         int key = 0;
548         event_poll();
549         if (key_data.keytail!=key_data.keyhead)
550                 key = key_data.keybuffer[key_data.keyhead];
551
552         return key;
553 }
554
555 int key_getch()
556 {
557         int dummy=0;
558
559         if (!Installed)
560                 return 0;
561 //              return getch();
562
563         while (!key_checkch())
564                 dummy++;
565         return key_inkey();
566 }
567
568 unsigned int key_get_shift_status()
569 {
570         unsigned int shift_status = 0;
571
572         if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
573                 shift_status |= KEY_SHIFTED;
574
575         if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
576                 shift_status |= KEY_ALTED;
577
578         if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
579                 shift_status |= KEY_CTRLED;
580
581 #ifndef NDEBUG
582         if (keyd_pressed[KEY_DELETE])
583                 shift_status |=KEY_DEBUGGED;
584 #endif
585
586         return shift_status;
587 }
588
589 // Returns the number of seconds this key has been down since last call.
590 fix key_down_time(int scancode)
591 {
592         fix time_down, time;
593
594         event_poll();
595         if ((scancode<0)|| (scancode>255)) return 0;
596
597         if (!keyd_pressed[scancode]) {
598                 time_down = key_data.keys[scancode].timehelddown;
599                 key_data.keys[scancode].timehelddown = 0;
600         } else {
601                 time = timer_get_fixed_seconds();
602                 time_down = time - key_data.keys[scancode].timewentdown;
603                 key_data.keys[scancode].timewentdown = time;
604         }
605
606         return time_down;
607 }
608
609 unsigned int key_down_count(int scancode)
610 {
611         int n;
612         event_poll();
613         if ((scancode<0)|| (scancode>255)) return 0;
614
615         n = key_data.keys[scancode].downcount;
616         key_data.keys[scancode].downcount = 0;
617
618         return n;
619 }
620
621 unsigned int key_up_count(int scancode)
622 {
623         int n;
624         event_poll();
625         if ((scancode<0)|| (scancode>255)) return 0;
626
627         n = key_data.keys[scancode].upcount;
628         key_data.keys[scancode].upcount = 0;
629
630         return n;
631 }