gint_strcat/src/keysc/getkey.c

126 lines
2.7 KiB
C

//---
// gint:keysc:getkey - High-level keyboard monitoring function
//---
#include <gint/keyboard.h>
#include <gint/defs/types.h>
#ifdef FX9860G
#include <gint/drivers/t6k11.h>
#endif
/* Delay between a key press and the first repeat, in scan intervals */
static int rep_first = 64;
/* Delay between subsequent repeats, in scan intervals */
static int rep_next = 8;
/* getkey() - wait for a pressed key */
key_event_t getkey(void)
{
return getkey_opt(GETKEY_DEFAULT, NULL);
}
/* getkey_opt() - enhanced getkey() */
key_event_t getkey_opt(int opt, volatile int *timeout)
{
key_event_t ev;
int shift = 0, alpha = 0, key = 0;
/* Last pressed key (only this key may be repeated) */
static int rep_key = 0;
/* Number of repeats already emitted */
static int rep_count = 0;
/* Scan intervals elapsed since last repeat */
static int rep_time = 0;
while(1) switch((ev = waitevent(timeout)).type)
{
/* Timeout has expired, return KEYEV_NONE */
case KEYEV_NONE:
return ev;
/* Key press: handle modifiers or return an event */
case KEYEV_DOWN:
key = ev.key;
/* Handle backlight on fx9860g */
#ifdef FX9860G
if(opt & GETKEY_BACKLIGHT && key == KEY_OPTN && shift)
{
t6k11_backlight(-1);
shift = 0;
continue;
}
#endif
/* Return to menu. TODO: use gint_switch() in getkey_opt() */
if(opt & GETKEY_MENU && key == KEY_MENU && !(alpha || shift))
{
continue;
}
/* Update modifiers */
if(opt & GETKEY_MOD_SHIFT && key == KEY_SHIFT)
{
shift ^= 1;
rep_key = 0;
continue;
}
if(opt & GETKEY_MOD_ALPHA && key == KEY_ALPHA)
{
alpha ^= 1;
rep_key = 0;
continue;
}
/* Return current event */
rep_key = key;
rep_count = 0;
rep_time = 0;
ev.mod = 1;
ev.shift = shift;
ev.alpha = alpha;
return ev;
/* Return new events when a key is held (maybe) */
case KEYEV_HOLD:
if(ev.key != rep_key) break;
/* Check that this key can be repeated */
int arrow = (rep_key == KEY_LEFT || rep_key == KEY_RIGHT ||
rep_key == KEY_UP || rep_key == KEY_DOWN);
if(!(opt & GETKEY_REP_ALL) && !(opt & GETKEY_REP_ARROWS &&
arrow)) break;
/* If the key is key pressed long enough, create a new event */
int target = (rep_count) ? rep_next : rep_first;
if(++rep_time < target) break;
rep_time -= target;
rep_count++;
ev.mod = 1;
ev.shift = shift;
ev.alpha = alpha;
return ev;
/* Reset repeating information if the repeated key is released */
case KEYEV_UP:
if(ev.key != rep_key) break;
rep_key = 0;
rep_count = 0;
rep_time = 0;
break;
}
}
/* getkey_repeat() - set repeat delays for getkey() */
void getkey_repeat(int first, int next)
{
rep_first = (first * KEYBOARD_SCAN_FREQUENCY) / 1000;
rep_next = (next * KEYBOARD_SCAN_FREQUENCY) / 1000;
}