Neater CSI driver; dispatch command handlers from an array
This commit is contained in:
parent
a6aa8c433b
commit
6645ee9718
218
driver-csi.c
218
driver-csi.c
|
@ -6,16 +6,40 @@
|
||||||
|
|
||||||
// There are 64 codes 0x40 - 0x7F
|
// There are 64 codes 0x40 - 0x7F
|
||||||
static int keyinfo_initialised = 0;
|
static int keyinfo_initialised = 0;
|
||||||
static struct keyinfo csi_ss3s[64];
|
|
||||||
static struct keyinfo ss3s[64];
|
static struct keyinfo ss3s[64];
|
||||||
static char ss3_kpalts[64];
|
static char ss3_kpalts[64];
|
||||||
static struct keyinfo csifuncs[35]; /* This value must be increased if more CSI function keys are added */
|
|
||||||
#define NCSIFUNCS (sizeof(csifuncs)/sizeof(csifuncs[0]))
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TermKey *tk;
|
TermKey *tk;
|
||||||
} TermKeyCsi;
|
} TermKeyCsi;
|
||||||
|
|
||||||
|
typedef TermKeyResult CsiHandler(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args);
|
||||||
|
static CsiHandler *csi_handlers[64];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for CSI/SS3 cmd keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct keyinfo csi_ss3s[64];
|
||||||
|
|
||||||
|
static TermKeyResult handle_csi_ss3_full(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
|
||||||
|
{
|
||||||
|
if(args > 1 && arg[1] != -1)
|
||||||
|
key->modifiers = arg[1] - 1;
|
||||||
|
else
|
||||||
|
key->modifiers = 0;
|
||||||
|
|
||||||
|
key->type = csi_ss3s[cmd - 0x40].type;
|
||||||
|
key->code.sym = csi_ss3s[cmd - 0x40].sym;
|
||||||
|
key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask);
|
||||||
|
key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set;
|
||||||
|
|
||||||
|
if(key->code.sym == TERMKEY_SYM_UNKNOWN)
|
||||||
|
return TERMKEY_RES_NONE;
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
static void register_csi_ss3_full(TermKeyType type, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char cmd)
|
static void register_csi_ss3_full(TermKeyType type, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char cmd)
|
||||||
{
|
{
|
||||||
if(cmd < 0x40 || cmd >= 0x80) {
|
if(cmd < 0x40 || cmd >= 0x80) {
|
||||||
|
@ -26,6 +50,8 @@ static void register_csi_ss3_full(TermKeyType type, TermKeySym sym, int modifier
|
||||||
csi_ss3s[cmd - 0x40].sym = sym;
|
csi_ss3s[cmd - 0x40].sym = sym;
|
||||||
csi_ss3s[cmd - 0x40].modifier_set = modifier_set;
|
csi_ss3s[cmd - 0x40].modifier_set = modifier_set;
|
||||||
csi_ss3s[cmd - 0x40].modifier_mask = modifier_mask;
|
csi_ss3s[cmd - 0x40].modifier_mask = modifier_mask;
|
||||||
|
|
||||||
|
csi_handlers[cmd - 0x40] = &handle_csi_ss3_full;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_csi_ss3(TermKeyType type, TermKeySym sym, unsigned char cmd)
|
static void register_csi_ss3(TermKeyType type, TermKeySym sym, unsigned char cmd)
|
||||||
|
@ -33,6 +59,10 @@ static void register_csi_ss3(TermKeyType type, TermKeySym sym, unsigned char cmd
|
||||||
register_csi_ss3_full(type, sym, 0, 0, cmd);
|
register_csi_ss3_full(type, sym, 0, 0, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for SS3 keys with kpad alternate representations
|
||||||
|
*/
|
||||||
|
|
||||||
static void register_ss3kpalt(TermKeyType type, TermKeySym sym, unsigned char cmd, char kpalt)
|
static void register_ss3kpalt(TermKeyType type, TermKeySym sym, unsigned char cmd, char kpalt)
|
||||||
{
|
{
|
||||||
if(cmd < 0x40 || cmd >= 0x80) {
|
if(cmd < 0x40 || cmd >= 0x80) {
|
||||||
|
@ -46,6 +76,46 @@ static void register_ss3kpalt(TermKeyType type, TermKeySym sym, unsigned char cm
|
||||||
ss3_kpalts[cmd - 0x40] = kpalt;
|
ss3_kpalts[cmd - 0x40] = kpalt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for CSI number ~ function keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct keyinfo csifuncs[35]; /* This value must be increased if more CSI function keys are added */
|
||||||
|
#define NCSIFUNCS (sizeof(csifuncs)/sizeof(csifuncs[0]))
|
||||||
|
|
||||||
|
static TermKeyResult handle_csifunc(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
|
||||||
|
{
|
||||||
|
if(args > 1 && arg[1] != -1)
|
||||||
|
key->modifiers = arg[1] - 1;
|
||||||
|
else
|
||||||
|
key->modifiers = 0;
|
||||||
|
|
||||||
|
key->type = TERMKEY_TYPE_KEYSYM;
|
||||||
|
|
||||||
|
if(arg[0] == 27) {
|
||||||
|
int mod = key->modifiers;
|
||||||
|
(*tk->method.emit_codepoint)(tk, arg[2], key);
|
||||||
|
key->modifiers |= mod;
|
||||||
|
}
|
||||||
|
else if(arg[0] >= 0 && arg[0] < NCSIFUNCS) {
|
||||||
|
key->type = csifuncs[arg[0]].type;
|
||||||
|
key->code.sym = csifuncs[arg[0]].sym;
|
||||||
|
key->modifiers &= ~(csifuncs[arg[0]].modifier_mask);
|
||||||
|
key->modifiers |= csifuncs[arg[0]].modifier_set;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
key->code.sym = TERMKEY_SYM_UNKNOWN;
|
||||||
|
|
||||||
|
if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "CSI: Unknown function key %ld\n", arg[0]);
|
||||||
|
#endif
|
||||||
|
return TERMKEY_RES_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
static void register_csifunc(TermKeyType type, TermKeySym sym, int number)
|
static void register_csifunc(TermKeyType type, TermKeySym sym, int number)
|
||||||
{
|
{
|
||||||
if(number >= NCSIFUNCS) {
|
if(number >= NCSIFUNCS) {
|
||||||
|
@ -56,6 +126,65 @@ static void register_csifunc(TermKeyType type, TermKeySym sym, int number)
|
||||||
csifuncs[number].sym = sym;
|
csifuncs[number].sym = sym;
|
||||||
csifuncs[number].modifier_set = 0;
|
csifuncs[number].modifier_set = 0;
|
||||||
csifuncs[number].modifier_mask = 0;
|
csifuncs[number].modifier_mask = 0;
|
||||||
|
|
||||||
|
csi_handlers['~' - 0x40] = &handle_csifunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for CSI u extended Unicode keys
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TermKeyResult handle_csi_unicode(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
|
||||||
|
{
|
||||||
|
if(args > 1 && arg[1] != -1)
|
||||||
|
key->modifiers = arg[1] - 1;
|
||||||
|
else
|
||||||
|
key->modifiers = 0;
|
||||||
|
|
||||||
|
int mod = key->modifiers;
|
||||||
|
key->type = TERMKEY_TYPE_KEYSYM;
|
||||||
|
(*tk->method.emit_codepoint)(tk, arg[0], key);
|
||||||
|
key->modifiers |= mod;
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for CSI M / CSI m mouse events in SRG and rxvt encodings
|
||||||
|
* Note: This does not handle X10 encoding
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TermKeyResult handle_csi_mouse(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
|
||||||
|
{
|
||||||
|
int initial = cmd >> 8;
|
||||||
|
cmd &= 0xff;
|
||||||
|
|
||||||
|
if(!initial && args >= 3) { // rxvt protocol
|
||||||
|
key->code.mouse[0] = arg[0];
|
||||||
|
|
||||||
|
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
|
||||||
|
key->code.mouse[0] &= ~0x1c;
|
||||||
|
|
||||||
|
termkey_key_set_linecol(key, arg[1], arg[2]);
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(initial == '<' && args >= 3) { // SGR protocol
|
||||||
|
key->code.mouse[0] = arg[0];
|
||||||
|
|
||||||
|
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
|
||||||
|
key->code.mouse[0] &= ~0x1c;
|
||||||
|
|
||||||
|
termkey_key_set_linecol(key, arg[1], arg[2]);
|
||||||
|
|
||||||
|
if(cmd == 'm') // release
|
||||||
|
key->code.mouse[3] |= 0x80;
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TERMKEY_RES_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int register_keys(void)
|
static int register_keys(void)
|
||||||
|
@ -134,6 +263,11 @@ static int register_keys(void)
|
||||||
register_csifunc(TERMKEY_TYPE_FUNCTION, 19, 33);
|
register_csifunc(TERMKEY_TYPE_FUNCTION, 19, 33);
|
||||||
register_csifunc(TERMKEY_TYPE_FUNCTION, 20, 34);
|
register_csifunc(TERMKEY_TYPE_FUNCTION, 20, 34);
|
||||||
|
|
||||||
|
csi_handlers['u' - 0x40] = &handle_csi_unicode;
|
||||||
|
|
||||||
|
csi_handlers['M' - 0x40] = &handle_csi_mouse;
|
||||||
|
csi_handlers['m' - 0x40] = &handle_csi_mouse;
|
||||||
|
|
||||||
keyinfo_initialised = 1;
|
keyinfo_initialised = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -227,71 +361,9 @@ static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen,
|
||||||
|
|
||||||
args++;
|
args++;
|
||||||
|
|
||||||
if(args > 1 && arg[1] != -1)
|
if(cmd == 'M' && args < 3) { // Mouse in X10 encoding consumes the next 3 bytes also
|
||||||
key->modifiers = arg[1] - 1;
|
|
||||||
else
|
|
||||||
key->modifiers = 0;
|
|
||||||
|
|
||||||
if(cmd == '~') {
|
|
||||||
key->type = TERMKEY_TYPE_KEYSYM;
|
|
||||||
|
|
||||||
if(arg[0] == 27) {
|
|
||||||
int mod = key->modifiers;
|
|
||||||
(*tk->method.emit_codepoint)(tk, arg[2], key);
|
|
||||||
key->modifiers |= mod;
|
|
||||||
}
|
|
||||||
else if(arg[0] >= 0 && arg[0] < NCSIFUNCS) {
|
|
||||||
key->type = csifuncs[arg[0]].type;
|
|
||||||
key->code.sym = csifuncs[arg[0]].sym;
|
|
||||||
key->modifiers &= ~(csifuncs[arg[0]].modifier_mask);
|
|
||||||
key->modifiers |= csifuncs[arg[0]].modifier_set;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
key->code.sym = TERMKEY_SYM_UNKNOWN;
|
|
||||||
|
|
||||||
if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "CSI: Unknown function key %ld\n", arg[0]);
|
|
||||||
#endif
|
|
||||||
return TERMKEY_RES_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(cmd == 'u') {
|
|
||||||
int mod = key->modifiers;
|
|
||||||
key->type = TERMKEY_TYPE_KEYSYM;
|
|
||||||
(*tk->method.emit_codepoint)(tk, arg[0], key);
|
|
||||||
key->modifiers |= mod;
|
|
||||||
}
|
|
||||||
else if(cmd == 'M' || (initial == '<' && cmd == 'm')) {
|
|
||||||
size_t csi_len = csi_end + 1;
|
size_t csi_len = csi_end + 1;
|
||||||
|
|
||||||
if(!initial && args >= 3) { // rxvt protocol
|
|
||||||
key->code.mouse[0] = arg[0];
|
|
||||||
|
|
||||||
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
|
|
||||||
key->code.mouse[0] &= ~0x1c;
|
|
||||||
|
|
||||||
termkey_key_set_linecol(key, arg[1], arg[2]);
|
|
||||||
|
|
||||||
*nbytep = csi_len;
|
|
||||||
return TERMKEY_RES_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(initial == '<' && args >= 3) { // SGR protocol
|
|
||||||
key->code.mouse[0] = arg[0];
|
|
||||||
|
|
||||||
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
|
|
||||||
key->code.mouse[0] &= ~0x1c;
|
|
||||||
|
|
||||||
termkey_key_set_linecol(key, arg[1], arg[2]);
|
|
||||||
|
|
||||||
if(cmd == 'm') // release
|
|
||||||
key->code.mouse[3] |= 0x80;
|
|
||||||
|
|
||||||
*nbytep = csi_len;
|
|
||||||
return TERMKEY_RES_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
tk->buffstart += csi_len;
|
tk->buffstart += csi_len;
|
||||||
tk->buffcount -= csi_len;
|
tk->buffcount -= csi_len;
|
||||||
|
|
||||||
|
@ -305,12 +377,12 @@ static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen,
|
||||||
|
|
||||||
return mouse_result;
|
return mouse_result;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
TermKeyResult result = TERMKEY_RES_NONE;
|
||||||
|
|
||||||
// We know from the logic above that cmd must be >= 0x40 and < 0x80
|
// We know from the logic above that cmd must be >= 0x40 and < 0x80
|
||||||
key->type = csi_ss3s[cmd - 0x40].type;
|
if(csi_handlers[cmd - 0x40])
|
||||||
key->code.sym = csi_ss3s[cmd - 0x40].sym;
|
result = (*csi_handlers[cmd - 0x40])(tk, key, (initial<<8)|cmd, arg, args);
|
||||||
key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask);
|
|
||||||
key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set;
|
|
||||||
|
|
||||||
if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
|
if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -331,11 +403,9 @@ static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen,
|
||||||
#endif
|
#endif
|
||||||
return TERMKEY_RES_NONE;
|
return TERMKEY_RES_NONE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*nbytep = csi_end + 1;
|
*nbytep = csi_end + 1;
|
||||||
|
return result;
|
||||||
return TERMKEY_RES_KEY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TermKeyResult peekkey_ss3(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep)
|
static TermKeyResult peekkey_ss3(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep)
|
||||||
|
|
Loading…
Reference in New Issue