aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-08-08 23:51:29 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2015-08-09 14:52:02 +0200
commitf05e40a30a008e0197fe0c8b192f399c448a95c6 (patch)
treefb3d2bb73687c6b56222196fca1fddec59d08e49
parent0b5d8ecd0d4119f7fa3e1ef8bc060c6c7124de14 (diff)
downloadtermo-f05e40a30a008e0197fe0c8b192f399c448a95c6.tar.gz
termo-f05e40a30a008e0197fe0c8b192f399c448a95c6.tar.xz
termo-f05e40a30a008e0197fe0c8b192f399c448a95c6.zip
Don't interpret an n*<Esc> as (n-1)*<Alt>-<Esc>
-rw-r--r--driver-csi.c20
-rw-r--r--driver-ti.c4
-rw-r--r--termo-internal.h8
-rw-r--r--termo.c33
-rw-r--r--tests/02getkey.c23
5 files changed, 64 insertions, 24 deletions
diff --git a/driver-csi.c b/driver-csi.c
index 1873e0d..7f6b008 100644
--- a/driver-csi.c
+++ b/driver-csi.c
@@ -708,7 +708,7 @@ free_driver (void *info)
static termo_result_t
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;
@@ -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);
if (ret == TERMO_RES_AGAIN)
{
- if (!force)
+ if (!(flags & PEEKKEY_FORCE))
return TERMO_RES_AGAIN;
(*tk->method.emit_codepoint) (tk, '[', key);
@@ -789,13 +789,13 @@ peekkey_csi (termo_t *tk, termo_csi_t *csi,
static termo_result_t
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;
if (tk->buffcount < introlen + 1)
{
- if (!force)
+ if (!(flags & PEEKKEY_FORCE))
return TERMO_RES_AGAIN;
(*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
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)
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
unsigned char b0 = CHARAT (0);
+ if (b0 == 0x1b && tk->buffcount == 1)
+ return TERMO_RES_AGAIN;
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')
- return peekkey_ss3 (tk, csi, 2, key, force, nbytep);
+ return peekkey_ss3 (tk, csi, 2, key, flags, nbytep);
if (b0 == 0x8f)
- return peekkey_ss3 (tk, csi, 1, key, force, nbytep);
+ return peekkey_ss3 (tk, csi, 1, key, flags, nbytep);
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;
}
diff --git a/driver-ti.c b/driver-ti.c
index 6ac213f..c94079f 100644
--- a/driver-ti.c
+++ b/driver-ti.c
@@ -466,7 +466,7 @@ free_driver (void *info)
static termo_result_t
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;
@@ -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
// partial match
- if (p && !force)
+ if (p && !(flags & PEEKKEY_FORCE))
return TERMO_RES_AGAIN;
return TERMO_RES_NONE;
diff --git a/termo-internal.h b/termo-internal.h
index adf3e8f..54948b0 100644
--- a/termo-internal.h
+++ b/termo-internal.h
@@ -37,6 +37,12 @@ struct termo_driver_node
termo_driver_node_t *next;
};
+enum peekey_flags
+{
+ PEEKKEY_FORCE = 1 << 0,
+ PEEKKEY_ALT_PREFIXED = 1 << 1
+};
+
struct termo
{
int fd;
@@ -75,7 +81,7 @@ struct termo
void (*emit_codepoint) (termo_t *tk,
uint32_t codepoint, termo_key_t *key);
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_key_t *key, size_t *nbytes);
}
diff --git a/termo.c b/termo.c
index 130ff40..704116b 100644
--- a/termo.c
+++ b/termo.c
@@ -37,7 +37,7 @@ static termo_driver_t *drivers[] =
// Forwards for the "protected" methods
static void emit_codepoint (termo_t *tk, uint32_t codepoint, termo_key_t *key);
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,
termo_key_t *key, size_t *nbytes);
@@ -860,7 +860,7 @@ termo_canonicalise (termo_t *tk, termo_key_t *key)
}
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;
@@ -887,7 +887,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
termo_driver_node_t *p;
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
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;
case TERMO_RES_AGAIN:
- if (!force)
+ if (!(flags & PEEKKEY_FORCE))
again = 1;
case TERMO_RES_NONE:
break;
@@ -926,7 +926,7 @@ peekkey (termo_t *tk, termo_key_t *key, int force, size_t *nbytep)
if (again)
return TERMO_RES_AGAIN;
- ret = peekkey_simple (tk, key, force, nbytep);
+ ret = peekkey_simple (tk, key, flags, nbytep);
#ifdef DEBUG
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
-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)
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);
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
if (tk->buffcount == 1)
{
// This might be an <Esc> press, or it may want to be part
// of a longer sequence
- if (!force)
+ if (!(flags & PEEKKEY_FORCE))
return TERMO_RES_AGAIN;
(*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--;
// 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->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
(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
// 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)
// 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
return ret;
@@ -1168,7 +1179,7 @@ termo_result_t
termo_getkey_force (termo_t *tk, termo_key_t *key)
{
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)
eat_bytes (tk, nbytes);
diff --git a/tests/02getkey.c b/tests/02getkey.c
index 94f71c7..b36eb9e 100644
--- a/tests/02getkey.c
+++ b/tests/02getkey.c
@@ -7,7 +7,7 @@ main (int argc, char *argv[])
termo_t *tk;
termo_key_t key;
- plan_tests (31);
+ plan_tests (38);
tk = termo_new_abstract ("vt100", NULL, 0);
@@ -86,6 +86,27 @@ main (int argc, char *argv[])
is_int (key.modifiers, TERMO_KEYMOD_CTRL,
"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);
return exit_status ();