Moved all of the C0 registration and 'do_codepoint' logic out of driver-csi back into termkey via another protected method 'emit_codepoint'
This commit is contained in:
parent
8407c53726
commit
d46f72fc1a
156
driver-csi.c
156
driver-csi.c
|
@ -4,19 +4,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct keyinfo {
|
|
||||||
termkey_type type;
|
|
||||||
termkey_keysym sym;
|
|
||||||
int modifier_mask;
|
|
||||||
int modifier_set;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
termkey_t *tk;
|
termkey_t *tk;
|
||||||
|
|
||||||
// There are 32 C0 codes
|
|
||||||
struct keyinfo c0[32];
|
|
||||||
|
|
||||||
// There are 64 codes 0x40 - 0x7F
|
// There are 64 codes 0x40 - 0x7F
|
||||||
struct keyinfo csi_ss3s[64];
|
struct keyinfo csi_ss3s[64];
|
||||||
struct keyinfo ss3s[64];
|
struct keyinfo ss3s[64];
|
||||||
|
@ -26,12 +16,10 @@ typedef struct {
|
||||||
struct keyinfo *csifuncs;
|
struct keyinfo *csifuncs;
|
||||||
} termkey_csi;
|
} termkey_csi;
|
||||||
|
|
||||||
static termkey_keysym register_c0(termkey_csi *csi, termkey_keysym sym, unsigned char ctrl, const char *name);
|
|
||||||
static termkey_keysym register_csi_ss3(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name);
|
static termkey_keysym register_csi_ss3(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name);
|
||||||
static termkey_keysym register_ss3kpalt(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name, char kpalt);
|
static termkey_keysym register_ss3kpalt(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name, char kpalt);
|
||||||
static termkey_keysym register_csifunc(termkey_csi *csi, termkey_type type, termkey_keysym sym, int number, const char *name);
|
static termkey_keysym register_csifunc(termkey_csi *csi, termkey_type type, termkey_keysym sym, int number, const char *name);
|
||||||
|
|
||||||
static termkey_keysym register_c0_full(termkey_csi *csi, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name);
|
|
||||||
static termkey_keysym register_csi_ss3_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char cmd, const char *name);
|
static termkey_keysym register_csi_ss3_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char cmd, const char *name);
|
||||||
static termkey_keysym register_ss3kpalt_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char cmd, const char *name, char kpalt);
|
static termkey_keysym register_ss3kpalt_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char cmd, const char *name, char kpalt);
|
||||||
static termkey_keysym register_csifunc_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, int number, const char *name);
|
static termkey_keysym register_csifunc_full(termkey_csi *csi, termkey_type type, termkey_keysym sym, int modifier_set, int modifier_mask, int number, const char *name);
|
||||||
|
@ -44,10 +32,6 @@ static void *new_driver(termkey_t *tk)
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < 32; i++) {
|
|
||||||
csi->c0[i].sym = TERMKEY_SYM_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 64; i++) {
|
for(i = 0; i < 64; i++) {
|
||||||
csi->csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
|
csi->csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
|
||||||
csi->ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
|
csi->ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
|
||||||
|
@ -61,11 +45,6 @@ static void *new_driver(termkey_t *tk)
|
||||||
for(i = 0; i < csi->ncsifuncs; i++)
|
for(i = 0; i < csi->ncsifuncs; i++)
|
||||||
csi->csifuncs[i].sym = TERMKEY_SYM_UNKNOWN;
|
csi->csifuncs[i].sym = TERMKEY_SYM_UNKNOWN;
|
||||||
|
|
||||||
register_c0(csi, TERMKEY_SYM_BACKSPACE, 0x08, "Backspace");
|
|
||||||
register_c0(csi, TERMKEY_SYM_TAB, 0x09, "Tab");
|
|
||||||
register_c0(csi, TERMKEY_SYM_ENTER, 0x0d, "Enter");
|
|
||||||
register_c0(csi, TERMKEY_SYM_ESCAPE, 0x1b, "Escape");
|
|
||||||
|
|
||||||
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A', "Up");
|
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A', "Up");
|
||||||
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B', "Down");
|
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B', "Down");
|
||||||
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C', "Right");
|
register_csi_ss3(csi, TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C', "Right");
|
||||||
|
@ -143,99 +122,6 @@ static void free_driver(void *private)
|
||||||
|
|
||||||
#define UTF8_INVALID 0xFFFD
|
#define UTF8_INVALID 0xFFFD
|
||||||
|
|
||||||
static int utf8_seqlen(int codepoint)
|
|
||||||
{
|
|
||||||
if(codepoint < 0x0000080) return 1;
|
|
||||||
if(codepoint < 0x0000800) return 2;
|
|
||||||
if(codepoint < 0x0010000) return 3;
|
|
||||||
if(codepoint < 0x0200000) return 4;
|
|
||||||
if(codepoint < 0x4000000) return 5;
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fill_utf8(termkey_key *key)
|
|
||||||
{
|
|
||||||
int codepoint = key->code.codepoint;
|
|
||||||
int nbytes = utf8_seqlen(codepoint);
|
|
||||||
|
|
||||||
key->utf8[nbytes] = 0;
|
|
||||||
|
|
||||||
// This is easier done backwards
|
|
||||||
int b = nbytes;
|
|
||||||
while(b > 1) {
|
|
||||||
b--;
|
|
||||||
key->utf8[b] = 0x80 | (codepoint & 0x3f);
|
|
||||||
codepoint >>= 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(nbytes) {
|
|
||||||
case 1: key->utf8[0] = (codepoint & 0x7f); break;
|
|
||||||
case 2: key->utf8[0] = 0xc0 | (codepoint & 0x1f); break;
|
|
||||||
case 3: key->utf8[0] = 0xe0 | (codepoint & 0x0f); break;
|
|
||||||
case 4: key->utf8[0] = 0xf0 | (codepoint & 0x07); break;
|
|
||||||
case 5: key->utf8[0] = 0xf8 | (codepoint & 0x03); break;
|
|
||||||
case 6: key->utf8[0] = 0xfc | (codepoint & 0x01); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void do_codepoint(termkey_t *tk, int codepoint, termkey_key *key)
|
|
||||||
{
|
|
||||||
termkey_csi *csi = tk->driver_info;
|
|
||||||
|
|
||||||
if(codepoint < 0x20) {
|
|
||||||
// C0 range
|
|
||||||
key->code.codepoint = 0;
|
|
||||||
key->modifiers = 0;
|
|
||||||
|
|
||||||
if(!(tk->flags & TERMKEY_FLAG_NOINTERPRET) && csi->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) {
|
|
||||||
key->code.sym = csi->c0[codepoint].sym;
|
|
||||||
key->modifiers |= csi->c0[codepoint].modifier_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!key->code.sym) {
|
|
||||||
key->type = TERMKEY_TYPE_UNICODE;
|
|
||||||
key->code.codepoint = codepoint + 0x40;
|
|
||||||
key->modifiers = TERMKEY_KEYMOD_CTRL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
key->type = TERMKEY_TYPE_KEYSYM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(codepoint == 0x20 && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
|
|
||||||
// ASCII space
|
|
||||||
key->type = TERMKEY_TYPE_KEYSYM;
|
|
||||||
key->code.sym = TERMKEY_SYM_SPACE;
|
|
||||||
key->modifiers = 0;
|
|
||||||
}
|
|
||||||
else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
|
|
||||||
// ASCII DEL
|
|
||||||
key->type = TERMKEY_TYPE_KEYSYM;
|
|
||||||
key->code.sym = TERMKEY_SYM_DEL;
|
|
||||||
key->modifiers = 0;
|
|
||||||
}
|
|
||||||
else if(codepoint >= 0x20 && codepoint < 0x80) {
|
|
||||||
// ASCII lowbyte range
|
|
||||||
key->type = TERMKEY_TYPE_UNICODE;
|
|
||||||
key->code.codepoint = codepoint;
|
|
||||||
key->modifiers = 0;
|
|
||||||
}
|
|
||||||
else if(codepoint >= 0x80 && codepoint < 0xa0) {
|
|
||||||
// UTF-8 never starts with a C1 byte. So we can be sure of these
|
|
||||||
key->type = TERMKEY_TYPE_UNICODE;
|
|
||||||
key->code.codepoint = codepoint - 0x40;
|
|
||||||
key->modifiers = TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// UTF-8 codepoint
|
|
||||||
key->type = TERMKEY_TYPE_UNICODE;
|
|
||||||
key->code.codepoint = codepoint;
|
|
||||||
key->modifiers = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key->type == TERMKEY_TYPE_UNICODE)
|
|
||||||
fill_utf8(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
||||||
|
|
||||||
static termkey_result getkey_csi(termkey_t *tk, size_t introlen, termkey_key *key)
|
static termkey_result getkey_csi(termkey_t *tk, size_t introlen, termkey_key *key)
|
||||||
|
@ -254,7 +140,7 @@ static termkey_result getkey_csi(termkey_t *tk, size_t introlen, termkey_key *ke
|
||||||
if(tk->waittime)
|
if(tk->waittime)
|
||||||
return TERMKEY_RES_AGAIN;
|
return TERMKEY_RES_AGAIN;
|
||||||
|
|
||||||
do_codepoint(tk, '[', key);
|
(*tk->method.emit_codepoint)(tk, '[', key);
|
||||||
key->modifiers |= TERMKEY_KEYMOD_ALT;
|
key->modifiers |= TERMKEY_KEYMOD_ALT;
|
||||||
(*tk->method.eat_bytes)(tk, introlen);
|
(*tk->method.eat_bytes)(tk, introlen);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
|
@ -310,7 +196,7 @@ static termkey_result getkey_csi(termkey_t *tk, size_t introlen, termkey_key *ke
|
||||||
|
|
||||||
if(arg[0] == 27) {
|
if(arg[0] == 27) {
|
||||||
int mod = key->modifiers;
|
int mod = key->modifiers;
|
||||||
do_codepoint(tk, arg[2], key);
|
(*tk->method.emit_codepoint)(tk, arg[2], key);
|
||||||
key->modifiers |= mod;
|
key->modifiers |= mod;
|
||||||
}
|
}
|
||||||
else if(arg[0] >= 0 && arg[0] < csi->ncsifuncs) {
|
else if(arg[0] >= 0 && arg[0] < csi->ncsifuncs) {
|
||||||
|
@ -347,7 +233,7 @@ static termkey_result getkey_ss3(termkey_t *tk, size_t introlen, termkey_key *ke
|
||||||
if(tk->waittime)
|
if(tk->waittime)
|
||||||
return TERMKEY_RES_AGAIN;
|
return TERMKEY_RES_AGAIN;
|
||||||
|
|
||||||
do_codepoint(tk, 'O', key);
|
(*tk->method.emit_codepoint)(tk, 'O', key);
|
||||||
key->modifiers |= TERMKEY_KEYMOD_ALT;
|
key->modifiers |= TERMKEY_KEYMOD_ALT;
|
||||||
(*tk->method.eat_bytes)(tk, tk->buffcount);
|
(*tk->method.eat_bytes)(tk, tk->buffcount);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
|
@ -402,7 +288,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
if(tk->waittime)
|
if(tk->waittime)
|
||||||
return TERMKEY_RES_AGAIN;
|
return TERMKEY_RES_AGAIN;
|
||||||
|
|
||||||
do_codepoint(tk, b0, key);
|
(*tk->method.emit_codepoint)(tk, b0, key);
|
||||||
(*tk->method.eat_bytes)(tk, 1);
|
(*tk->method.eat_bytes)(tk, 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -416,7 +302,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
return getkey_ss3(tk, 2, key);
|
return getkey_ss3(tk, 2, key);
|
||||||
|
|
||||||
if(b1 == 0x1b) {
|
if(b1 == 0x1b) {
|
||||||
do_codepoint(tk, b0, key);
|
(*tk->method.emit_codepoint)(tk, b0, key);
|
||||||
(*tk->method.eat_bytes)(tk, 1);
|
(*tk->method.eat_bytes)(tk, 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +334,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
}
|
}
|
||||||
else if(b0 < 0xa0) {
|
else if(b0 < 0xa0) {
|
||||||
// Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte
|
// Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte
|
||||||
do_codepoint(tk, b0, key);
|
(*tk->method.emit_codepoint)(tk, b0, key);
|
||||||
(*tk->method.eat_bytes)(tk, 1);
|
(*tk->method.eat_bytes)(tk, 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +348,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
|
|
||||||
if(b0 < 0xc0) {
|
if(b0 < 0xc0) {
|
||||||
// Starts with a continuation byte - that's not right
|
// Starts with a continuation byte - that's not right
|
||||||
do_codepoint(tk, UTF8_INVALID, key);
|
(*tk->method.emit_codepoint)(tk, UTF8_INVALID, key);
|
||||||
(*tk->method.eat_bytes)(tk, 1);
|
(*tk->method.eat_bytes)(tk, 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -487,7 +373,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
codepoint = b0 & 0x01;
|
codepoint = b0 & 0x01;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
do_codepoint(tk, UTF8_INVALID, key);
|
(*tk->method.emit_codepoint)(tk, UTF8_INVALID, key);
|
||||||
(*tk->method.eat_bytes)(tk, 1);
|
(*tk->method.eat_bytes)(tk, 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -498,7 +384,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
for(int b = 1; b < nbytes; b++) {
|
for(int b = 1; b < nbytes; b++) {
|
||||||
unsigned char cb = CHARAT(b);
|
unsigned char cb = CHARAT(b);
|
||||||
if(cb < 0x80 || cb >= 0xc0) {
|
if(cb < 0x80 || cb >= 0xc0) {
|
||||||
do_codepoint(tk, UTF8_INVALID, key);
|
(*tk->method.emit_codepoint)(tk, UTF8_INVALID, key);
|
||||||
(*tk->method.eat_bytes)(tk, b - 1);
|
(*tk->method.eat_bytes)(tk, b - 1);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -517,7 +403,7 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
codepoint == 0xFFFF)
|
codepoint == 0xFFFF)
|
||||||
codepoint = UTF8_INVALID;
|
codepoint = UTF8_INVALID;
|
||||||
|
|
||||||
do_codepoint(tk, codepoint, key);
|
(*tk->method.emit_codepoint)(tk, codepoint, key);
|
||||||
(*tk->method.eat_bytes)(tk, nbytes);
|
(*tk->method.eat_bytes)(tk, nbytes);
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
@ -538,28 +424,6 @@ static termkey_result getkey(termkey_t *tk, termkey_key *key)
|
||||||
return TERMKEY_SYM_NONE;
|
return TERMKEY_SYM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static termkey_keysym register_c0(termkey_csi *csi, termkey_keysym sym, unsigned char ctrl, const char *name)
|
|
||||||
{
|
|
||||||
return register_c0_full(csi, sym, 0, 0, ctrl, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static termkey_keysym register_c0_full(termkey_csi *csi, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name)
|
|
||||||
{
|
|
||||||
if(ctrl >= 0x20) {
|
|
||||||
fprintf(stderr, "Cannot register C0 key at ctrl 0x%02x - out of bounds\n", ctrl);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(name)
|
|
||||||
sym = termkey_register_keyname(csi->tk, sym, name);
|
|
||||||
|
|
||||||
csi->c0[ctrl].sym = sym;
|
|
||||||
csi->c0[ctrl].modifier_set = modifier_set;
|
|
||||||
csi->c0[ctrl].modifier_mask = modifier_mask;
|
|
||||||
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
static termkey_keysym register_csi_ss3(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name)
|
static termkey_keysym register_csi_ss3(termkey_csi *csi, termkey_type type, termkey_keysym sym, unsigned char cmd, const char *name)
|
||||||
{
|
{
|
||||||
return register_csi_ss3_full(csi, type, sym, 0, 0, cmd, name);
|
return register_csi_ss3_full(csi, type, sym, 0, 0, cmd, name);
|
||||||
|
|
|
@ -13,6 +13,13 @@ struct termkey_driver
|
||||||
termkey_result (*getkey)(termkey_t *tk, termkey_key *key);
|
termkey_result (*getkey)(termkey_t *tk, termkey_key *key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct keyinfo {
|
||||||
|
termkey_type type;
|
||||||
|
termkey_keysym sym;
|
||||||
|
int modifier_mask;
|
||||||
|
int modifier_set;
|
||||||
|
};
|
||||||
|
|
||||||
struct termkey {
|
struct termkey {
|
||||||
int fd;
|
int fd;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -31,6 +38,9 @@ struct termkey {
|
||||||
int nkeynames;
|
int nkeynames;
|
||||||
const char **keynames;
|
const char **keynames;
|
||||||
|
|
||||||
|
// There are 32 C0 codes
|
||||||
|
struct keyinfo c0[32];
|
||||||
|
|
||||||
struct termkey_driver driver;
|
struct termkey_driver driver;
|
||||||
void *driver_info;
|
void *driver_info;
|
||||||
|
|
||||||
|
@ -38,9 +48,21 @@ struct termkey {
|
||||||
// want exported as real symbols in the library
|
// want exported as real symbols in the library
|
||||||
struct {
|
struct {
|
||||||
void (*eat_bytes)(termkey_t *tk, size_t count);
|
void (*eat_bytes)(termkey_t *tk, size_t count);
|
||||||
|
void (*emit_codepoint)(termkey_t *tk, int codepoint, termkey_key *key);
|
||||||
} method;
|
} method;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct termkey_driver termkey_driver_csi;
|
extern struct termkey_driver termkey_driver_csi;
|
||||||
|
|
||||||
|
// Keep this here for now since it's tiny
|
||||||
|
static inline int utf8_seqlen(int codepoint)
|
||||||
|
{
|
||||||
|
if(codepoint < 0x0000080) return 1;
|
||||||
|
if(codepoint < 0x0000800) return 2;
|
||||||
|
if(codepoint < 0x0010000) return 3;
|
||||||
|
if(codepoint < 0x0200000) return 4;
|
||||||
|
if(codepoint < 0x4000000) return 5;
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
116
termkey.c
116
termkey.c
|
@ -15,6 +15,10 @@ static struct termkey_driver *drivers[] = {
|
||||||
|
|
||||||
// Forwards for the "protected" methods
|
// Forwards for the "protected" methods
|
||||||
static void eat_bytes(termkey_t *tk, size_t count);
|
static void eat_bytes(termkey_t *tk, size_t count);
|
||||||
|
static void emit_codepoint(termkey_t *tk, int codepoint, termkey_key *key);
|
||||||
|
|
||||||
|
static termkey_keysym register_c0(termkey_t *tk, termkey_keysym sym, unsigned char ctrl, const char *name);
|
||||||
|
static termkey_keysym register_c0_full(termkey_t *tk, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name);
|
||||||
|
|
||||||
termkey_t *termkey_new_full(int fd, int flags, size_t buffsize, int waittime)
|
termkey_t *termkey_new_full(int fd, int flags, size_t buffsize, int waittime)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +71,16 @@ termkey_t *termkey_new_full(int fd, int flags, size_t buffsize, int waittime)
|
||||||
for(i = 0; i < tk->nkeynames; i++)
|
for(i = 0; i < tk->nkeynames; i++)
|
||||||
tk->keynames[i] = NULL;
|
tk->keynames[i] = NULL;
|
||||||
|
|
||||||
|
for(i = 0; i < 32; i++)
|
||||||
|
tk->c0[i].sym = TERMKEY_SYM_NONE;
|
||||||
|
|
||||||
tk->method.eat_bytes = &eat_bytes;
|
tk->method.eat_bytes = &eat_bytes;
|
||||||
|
tk->method.emit_codepoint = &emit_codepoint;
|
||||||
|
|
||||||
|
register_c0(tk, TERMKEY_SYM_BACKSPACE, 0x08, "Backspace");
|
||||||
|
register_c0(tk, TERMKEY_SYM_TAB, 0x09, "Tab");
|
||||||
|
register_c0(tk, TERMKEY_SYM_ENTER, 0x0d, "Enter");
|
||||||
|
register_c0(tk, TERMKEY_SYM_ESCAPE, 0x1b, "Escape");
|
||||||
|
|
||||||
for(i = 0; drivers[i]; i++) {
|
for(i = 0; drivers[i]; i++) {
|
||||||
void *driver_info = (*drivers[i]->new_driver)(tk);
|
void *driver_info = (*drivers[i]->new_driver)(tk);
|
||||||
|
@ -157,6 +170,87 @@ static void eat_bytes(termkey_t *tk, size_t count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fill_utf8(termkey_key *key)
|
||||||
|
{
|
||||||
|
int codepoint = key->code.codepoint;
|
||||||
|
int nbytes = utf8_seqlen(codepoint);
|
||||||
|
|
||||||
|
key->utf8[nbytes] = 0;
|
||||||
|
|
||||||
|
// This is easier done backwards
|
||||||
|
int b = nbytes;
|
||||||
|
while(b > 1) {
|
||||||
|
b--;
|
||||||
|
key->utf8[b] = 0x80 | (codepoint & 0x3f);
|
||||||
|
codepoint >>= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(nbytes) {
|
||||||
|
case 1: key->utf8[0] = (codepoint & 0x7f); break;
|
||||||
|
case 2: key->utf8[0] = 0xc0 | (codepoint & 0x1f); break;
|
||||||
|
case 3: key->utf8[0] = 0xe0 | (codepoint & 0x0f); break;
|
||||||
|
case 4: key->utf8[0] = 0xf0 | (codepoint & 0x07); break;
|
||||||
|
case 5: key->utf8[0] = 0xf8 | (codepoint & 0x03); break;
|
||||||
|
case 6: key->utf8[0] = 0xfc | (codepoint & 0x01); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_codepoint(termkey_t *tk, int codepoint, termkey_key *key)
|
||||||
|
{
|
||||||
|
if(codepoint < 0x20) {
|
||||||
|
// C0 range
|
||||||
|
key->code.codepoint = 0;
|
||||||
|
key->modifiers = 0;
|
||||||
|
|
||||||
|
if(!(tk->flags & TERMKEY_FLAG_NOINTERPRET) && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) {
|
||||||
|
key->code.sym = tk->c0[codepoint].sym;
|
||||||
|
key->modifiers |= tk->c0[codepoint].modifier_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!key->code.sym) {
|
||||||
|
key->type = TERMKEY_TYPE_UNICODE;
|
||||||
|
key->code.codepoint = codepoint + 0x40;
|
||||||
|
key->modifiers = TERMKEY_KEYMOD_CTRL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
key->type = TERMKEY_TYPE_KEYSYM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(codepoint == 0x20 && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
|
||||||
|
// ASCII space
|
||||||
|
key->type = TERMKEY_TYPE_KEYSYM;
|
||||||
|
key->code.sym = TERMKEY_SYM_SPACE;
|
||||||
|
key->modifiers = 0;
|
||||||
|
}
|
||||||
|
else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
|
||||||
|
// ASCII DEL
|
||||||
|
key->type = TERMKEY_TYPE_KEYSYM;
|
||||||
|
key->code.sym = TERMKEY_SYM_DEL;
|
||||||
|
key->modifiers = 0;
|
||||||
|
}
|
||||||
|
else if(codepoint >= 0x20 && codepoint < 0x80) {
|
||||||
|
// ASCII lowbyte range
|
||||||
|
key->type = TERMKEY_TYPE_UNICODE;
|
||||||
|
key->code.codepoint = codepoint;
|
||||||
|
key->modifiers = 0;
|
||||||
|
}
|
||||||
|
else if(codepoint >= 0x80 && codepoint < 0xa0) {
|
||||||
|
// UTF-8 never starts with a C1 byte. So we can be sure of these
|
||||||
|
key->type = TERMKEY_TYPE_UNICODE;
|
||||||
|
key->code.codepoint = codepoint - 0x40;
|
||||||
|
key->modifiers = TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// UTF-8 codepoint
|
||||||
|
key->type = TERMKEY_TYPE_UNICODE;
|
||||||
|
key->code.codepoint = codepoint;
|
||||||
|
key->modifiers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key->type == TERMKEY_TYPE_UNICODE)
|
||||||
|
fill_utf8(key);
|
||||||
|
}
|
||||||
|
|
||||||
termkey_result termkey_getkey(termkey_t *tk, termkey_key *key)
|
termkey_result termkey_getkey(termkey_t *tk, termkey_key *key)
|
||||||
{
|
{
|
||||||
return (*tk->driver.getkey)(tk, key);
|
return (*tk->driver.getkey)(tk, key);
|
||||||
|
@ -273,6 +367,28 @@ const char *termkey_get_keyname(termkey_t *tk, termkey_keysym sym)
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static termkey_keysym register_c0(termkey_t *tk, termkey_keysym sym, unsigned char ctrl, const char *name)
|
||||||
|
{
|
||||||
|
return register_c0_full(tk, sym, 0, 0, ctrl, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static termkey_keysym register_c0_full(termkey_t *tk, termkey_keysym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name)
|
||||||
|
{
|
||||||
|
if(ctrl >= 0x20) {
|
||||||
|
fprintf(stderr, "Cannot register C0 key at ctrl 0x%02x - out of bounds\n", ctrl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name)
|
||||||
|
sym = termkey_register_keyname(tk, sym, name);
|
||||||
|
|
||||||
|
tk->c0[ctrl].sym = sym;
|
||||||
|
tk->c0[ctrl].modifier_set = modifier_set;
|
||||||
|
tk->c0[ctrl].modifier_mask = modifier_mask;
|
||||||
|
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
size_t termkey_snprint_key(termkey_t *tk, char *buffer, size_t len, termkey_key *key, termkey_format format)
|
size_t termkey_snprint_key(termkey_t *tk, char *buffer, size_t len, termkey_key *key, termkey_format format)
|
||||||
{
|
{
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|
Loading…
Reference in New Issue