Don't interpret an n*<Esc> as (n-1)*<Alt>-<Esc>
This commit is contained in:
parent
0b5d8ecd0d
commit
f05e40a30a
20
driver-csi.c
20
driver-csi.c
|
@ -708,7 +708,7 @@ free_driver (void *info)
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey_csi (termo_t *tk, termo_csi_t *csi,
|
peekkey_csi (termo_t *tk, termo_csi_t *csi,
|
||||||
size_t introlen, termo_key_t *key, int force, size_t *nbytep)
|
size_t introlen, termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
(void) csi;
|
(void) csi;
|
||||||
|
|
||||||
|
@ -720,7 +720,7 @@ peekkey_csi (termo_t *tk, termo_csi_t *csi,
|
||||||
termo_result_t ret = parse_csi (tk, introlen, &csi_len, arg, &args, &cmd);
|
termo_result_t ret = parse_csi (tk, introlen, &csi_len, arg, &args, &cmd);
|
||||||
if (ret == TERMO_RES_AGAIN)
|
if (ret == TERMO_RES_AGAIN)
|
||||||
{
|
{
|
||||||
if (!force)
|
if (!(flags & PEEKKEY_FORCE))
|
||||||
return TERMO_RES_AGAIN;
|
return TERMO_RES_AGAIN;
|
||||||
|
|
||||||
(*tk->method.emit_codepoint) (tk, '[', key);
|
(*tk->method.emit_codepoint) (tk, '[', key);
|
||||||
|
@ -789,13 +789,13 @@ peekkey_csi (termo_t *tk, termo_csi_t *csi,
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey_ss3 (termo_t *tk, termo_csi_t *csi, size_t introlen,
|
peekkey_ss3 (termo_t *tk, termo_csi_t *csi, size_t introlen,
|
||||||
termo_key_t *key, int force, size_t *nbytep)
|
termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
(void) csi;
|
(void) csi;
|
||||||
|
|
||||||
if (tk->buffcount < introlen + 1)
|
if (tk->buffcount < introlen + 1)
|
||||||
{
|
{
|
||||||
if (!force)
|
if (!(flags & PEEKKEY_FORCE))
|
||||||
return TERMO_RES_AGAIN;
|
return TERMO_RES_AGAIN;
|
||||||
|
|
||||||
(*tk->method.emit_codepoint) (tk, 'O', key);
|
(*tk->method.emit_codepoint) (tk, 'O', key);
|
||||||
|
@ -847,7 +847,7 @@ peekkey_ss3 (termo_t *tk, termo_csi_t *csi, size_t introlen,
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey (termo_t *tk, void *info,
|
peekkey (termo_t *tk, void *info,
|
||||||
termo_key_t *key, int force, size_t *nbytep)
|
termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
if (tk->buffcount == 0)
|
if (tk->buffcount == 0)
|
||||||
return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
|
return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
|
||||||
|
@ -857,14 +857,16 @@ peekkey (termo_t *tk, void *info,
|
||||||
// Now we're sure at least 1 byte is valid
|
// Now we're sure at least 1 byte is valid
|
||||||
unsigned char b0 = CHARAT (0);
|
unsigned char b0 = CHARAT (0);
|
||||||
|
|
||||||
|
if (b0 == 0x1b && tk->buffcount == 1)
|
||||||
|
return TERMO_RES_AGAIN;
|
||||||
if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == '[')
|
if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == '[')
|
||||||
return peekkey_csi (tk, csi, 2, key, force, nbytep);
|
return peekkey_csi (tk, csi, 2, key, flags, nbytep);
|
||||||
if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == 'O')
|
if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == 'O')
|
||||||
return peekkey_ss3 (tk, csi, 2, key, force, nbytep);
|
return peekkey_ss3 (tk, csi, 2, key, flags, nbytep);
|
||||||
if (b0 == 0x8f)
|
if (b0 == 0x8f)
|
||||||
return peekkey_ss3 (tk, csi, 1, key, force, nbytep);
|
return peekkey_ss3 (tk, csi, 1, key, flags, nbytep);
|
||||||
if (b0 == 0x9b)
|
if (b0 == 0x9b)
|
||||||
return peekkey_csi (tk, csi, 1, key, force, nbytep);
|
return peekkey_csi (tk, csi, 1, key, flags, nbytep);
|
||||||
return TERMO_RES_NONE;
|
return TERMO_RES_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -466,7 +466,7 @@ free_driver (void *info)
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey (termo_t *tk, void *info,
|
peekkey (termo_t *tk, void *info,
|
||||||
termo_key_t *key, int force, size_t *nbytep)
|
termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
termo_ti_t *ti = info;
|
termo_ti_t *ti = info;
|
||||||
|
|
||||||
|
@ -512,7 +512,7 @@ peekkey (termo_t *tk, void *info,
|
||||||
|
|
||||||
// If p is not NULL then we hadn't walked off the end yet, so we have a
|
// If p is not NULL then we hadn't walked off the end yet, so we have a
|
||||||
// partial match
|
// partial match
|
||||||
if (p && !force)
|
if (p && !(flags & PEEKKEY_FORCE))
|
||||||
return TERMO_RES_AGAIN;
|
return TERMO_RES_AGAIN;
|
||||||
|
|
||||||
return TERMO_RES_NONE;
|
return TERMO_RES_NONE;
|
||||||
|
|
|
@ -37,6 +37,12 @@ struct termo_driver_node
|
||||||
termo_driver_node_t *next;
|
termo_driver_node_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum peekey_flags
|
||||||
|
{
|
||||||
|
PEEKKEY_FORCE = 1 << 0,
|
||||||
|
PEEKKEY_ALT_PREFIXED = 1 << 1
|
||||||
|
};
|
||||||
|
|
||||||
struct termo
|
struct termo
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -75,7 +81,7 @@ struct termo
|
||||||
void (*emit_codepoint) (termo_t *tk,
|
void (*emit_codepoint) (termo_t *tk,
|
||||||
uint32_t codepoint, termo_key_t *key);
|
uint32_t codepoint, termo_key_t *key);
|
||||||
termo_result_t (*peekkey_simple) (termo_t *tk,
|
termo_result_t (*peekkey_simple) (termo_t *tk,
|
||||||
termo_key_t *key, int force, size_t *nbytes);
|
termo_key_t *key, int flags, size_t *nbytes);
|
||||||
termo_result_t (*peekkey_mouse) (termo_t *tk,
|
termo_result_t (*peekkey_mouse) (termo_t *tk,
|
||||||
termo_key_t *key, size_t *nbytes);
|
termo_key_t *key, size_t *nbytes);
|
||||||
}
|
}
|
||||||
|
|
33
termo.c
33
termo.c
|
@ -37,7 +37,7 @@ static termo_driver_t *drivers[] =
|
||||||
// Forwards for the "protected" methods
|
// Forwards for the "protected" methods
|
||||||
static void emit_codepoint (termo_t *tk, uint32_t codepoint, termo_key_t *key);
|
static void emit_codepoint (termo_t *tk, uint32_t codepoint, termo_key_t *key);
|
||||||
static termo_result_t peekkey_simple (termo_t *tk,
|
static termo_result_t peekkey_simple (termo_t *tk,
|
||||||
termo_key_t *key, int force, size_t *nbytes);
|
termo_key_t *key, int flags, size_t *nbytes);
|
||||||
static termo_result_t peekkey_mouse (termo_t *tk,
|
static termo_result_t peekkey_mouse (termo_t *tk,
|
||||||
termo_key_t *key, size_t *nbytes);
|
termo_key_t *key, size_t *nbytes);
|
||||||
|
|
||||||
|
@ -860,7 +860,7 @@ termo_canonicalise (termo_t *tk, termo_key_t *key)
|
||||||
}
|
}
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
peekkey (termo_t *tk, termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
int again = 0;
|
int again = 0;
|
||||||
|
|
||||||
|
@ -887,7 +887,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
termo_driver_node_t *p;
|
termo_driver_node_t *p;
|
||||||
for (p = tk->drivers; p; p = p->next)
|
for (p = tk->drivers; p; p = p->next)
|
||||||
{
|
{
|
||||||
ret = (p->driver->peekkey) (tk, p->info, key, force, nbytep);
|
ret = (p->driver->peekkey) (tk, p->info, key, flags, nbytep);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "Driver %s yields %s\n",
|
fprintf (stderr, "Driver %s yields %s\n",
|
||||||
|
@ -916,7 +916,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
case TERMO_RES_AGAIN:
|
case TERMO_RES_AGAIN:
|
||||||
if (!force)
|
if (!(flags & PEEKKEY_FORCE))
|
||||||
again = 1;
|
again = 1;
|
||||||
case TERMO_RES_NONE:
|
case TERMO_RES_NONE:
|
||||||
break;
|
break;
|
||||||
|
@ -926,7 +926,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
if (again)
|
if (again)
|
||||||
return TERMO_RES_AGAIN;
|
return TERMO_RES_AGAIN;
|
||||||
|
|
||||||
ret = peekkey_simple (tk, key, force, nbytep);
|
ret = peekkey_simple (tk, key, flags, nbytep);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "getkey_simple(force=%d) yields %s\n",
|
fprintf (stderr, "getkey_simple(force=%d) yields %s\n",
|
||||||
|
@ -942,7 +942,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
}
|
}
|
||||||
|
|
||||||
static termo_result_t
|
static termo_result_t
|
||||||
peekkey_simple (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
peekkey_simple (termo_t *tk, termo_key_t *key, int flags, size_t *nbytep)
|
||||||
{
|
{
|
||||||
if (tk->buffcount == 0)
|
if (tk->buffcount == 0)
|
||||||
return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
|
return tk->is_closed ? TERMO_RES_EOF : TERMO_RES_NONE;
|
||||||
|
@ -950,12 +950,22 @@ peekkey_simple (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
unsigned char b0 = CHARAT (0);
|
unsigned char b0 = CHARAT (0);
|
||||||
if (b0 == 0x1b)
|
if (b0 == 0x1b)
|
||||||
{
|
{
|
||||||
|
if (flags & PEEKKEY_ALT_PREFIXED)
|
||||||
|
{
|
||||||
|
// We got back here recursively, which means that no driver has
|
||||||
|
// returned TERMO_RES_AGAIN -> just return the Escape. Otherwise
|
||||||
|
// we would interpret an indefinite number of <Esc>s as Alt+Esc.
|
||||||
|
(*tk->method.emit_codepoint) (tk, b0, key);
|
||||||
|
*nbytep = 1;
|
||||||
|
return TERMO_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
// Escape-prefixed value? Might therefore be Alt+key
|
// Escape-prefixed value? Might therefore be Alt+key
|
||||||
if (tk->buffcount == 1)
|
if (tk->buffcount == 1)
|
||||||
{
|
{
|
||||||
// This might be an <Esc> press, or it may want to be part
|
// This might be an <Esc> press, or it may want to be part
|
||||||
// of a longer sequence
|
// of a longer sequence
|
||||||
if (!force)
|
if (!(flags & PEEKKEY_FORCE))
|
||||||
return TERMO_RES_AGAIN;
|
return TERMO_RES_AGAIN;
|
||||||
|
|
||||||
(*tk->method.emit_codepoint) (tk, b0, key);
|
(*tk->method.emit_codepoint) (tk, b0, key);
|
||||||
|
@ -968,7 +978,8 @@ peekkey_simple (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
tk->buffcount--;
|
tk->buffcount--;
|
||||||
|
|
||||||
// Run the full driver
|
// Run the full driver
|
||||||
termo_result_t metakey_result = peekkey (tk, key, force, nbytep);
|
termo_result_t metakey_result =
|
||||||
|
peekkey (tk, key, flags | PEEKKEY_ALT_PREFIXED, nbytep);
|
||||||
|
|
||||||
tk->buffstart--;
|
tk->buffstart--;
|
||||||
tk->buffcount++;
|
tk->buffcount++;
|
||||||
|
@ -998,7 +1009,7 @@ peekkey_simple (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
|
||||||
termo_result_t res = parse_multibyte
|
termo_result_t res = parse_multibyte
|
||||||
(tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
|
(tk, tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
|
||||||
|
|
||||||
if (res == TERMO_RES_AGAIN && force)
|
if (res == TERMO_RES_AGAIN && (flags & PEEKKEY_FORCE))
|
||||||
{
|
{
|
||||||
// There weren't enough bytes for a complete character but
|
// There weren't enough bytes for a complete character but
|
||||||
// caller demands an answer. About the best thing we can do here
|
// caller demands an answer. About the best thing we can do here
|
||||||
|
@ -1158,7 +1169,7 @@ termo_getkey (termo_t *tk, termo_key_t *key)
|
||||||
|
|
||||||
if (ret == TERMO_RES_AGAIN)
|
if (ret == TERMO_RES_AGAIN)
|
||||||
// Call peekkey() again in force mode to obtain whatever it can
|
// Call peekkey() again in force mode to obtain whatever it can
|
||||||
(void) peekkey (tk, key, 1, &nbytes);
|
(void) peekkey (tk, key, PEEKKEY_FORCE, &nbytes);
|
||||||
// Don't eat it yet though
|
// Don't eat it yet though
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1168,7 +1179,7 @@ termo_result_t
|
||||||
termo_getkey_force (termo_t *tk, termo_key_t *key)
|
termo_getkey_force (termo_t *tk, termo_key_t *key)
|
||||||
{
|
{
|
||||||
size_t nbytes = 0;
|
size_t nbytes = 0;
|
||||||
termo_result_t ret = peekkey (tk, key, 1, &nbytes);
|
termo_result_t ret = peekkey (tk, key, PEEKKEY_FORCE, &nbytes);
|
||||||
|
|
||||||
if (ret == TERMO_RES_KEY)
|
if (ret == TERMO_RES_KEY)
|
||||||
eat_bytes (tk, nbytes);
|
eat_bytes (tk, nbytes);
|
||||||
|
|
|
@ -7,7 +7,7 @@ main (int argc, char *argv[])
|
||||||
termo_t *tk;
|
termo_t *tk;
|
||||||
termo_key_t key;
|
termo_key_t key;
|
||||||
|
|
||||||
plan_tests (31);
|
plan_tests (38);
|
||||||
|
|
||||||
tk = termo_new_abstract ("vt100", NULL, 0);
|
tk = termo_new_abstract ("vt100", NULL, 0);
|
||||||
|
|
||||||
|
@ -86,6 +86,27 @@ main (int argc, char *argv[])
|
||||||
is_int (key.modifiers, TERMO_KEYMOD_CTRL,
|
is_int (key.modifiers, TERMO_KEYMOD_CTRL,
|
||||||
"key.modifiers after Ctrl-Escape");
|
"key.modifiers after Ctrl-Escape");
|
||||||
|
|
||||||
|
// Escape key in various amounts
|
||||||
|
|
||||||
|
termo_push_bytes (tk, "\x1b\x1b", 2);
|
||||||
|
is_int (termo_getkey (tk, &key), TERMO_RES_AGAIN,
|
||||||
|
"two Escapes don't yield anything");
|
||||||
|
is_int (termo_get_buffer_remaining (tk), 254,
|
||||||
|
"buffer free 254 after two Escapes");
|
||||||
|
|
||||||
|
termo_push_bytes (tk, "\x1b", 1);
|
||||||
|
is_int (termo_getkey (tk, &key), TERMO_RES_KEY,
|
||||||
|
"three Escapes yield Alt-Escape");
|
||||||
|
is_int (termo_get_buffer_remaining (tk), 255,
|
||||||
|
"buffer free 255 after three Escapes");
|
||||||
|
|
||||||
|
is_int (key.type, TERMO_TYPE_KEYSYM,
|
||||||
|
"key.type after three Escapes");
|
||||||
|
is_int (key.code.sym, TERMO_SYM_ESCAPE,
|
||||||
|
"key.code.sym after three Escapes");
|
||||||
|
is_int (key.modifiers, TERMO_KEYMOD_ALT,
|
||||||
|
"key.modifiers after three Escapes");
|
||||||
|
|
||||||
termo_destroy (tk);
|
termo_destroy (tk);
|
||||||
|
|
||||||
return exit_status ();
|
return exit_status ();
|
||||||
|
|
Loading…
Reference in New Issue