From e330d751a42def1e014227d5e39969af6e87591f Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Mon, 13 Oct 2014 23:36:14 +0200
Subject: Make mode 1015 and 1006 work, prepare for 1005
---
driver-csi.c | 37 ++++++++--------
termkey2-internal.h | 19 ++++-----
termkey2.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++-----
termkey2.h | 11 +++--
4 files changed, 144 insertions(+), 43 deletions(-)
diff --git a/driver-csi.c b/driver-csi.c
index 9f822f0..a7fcc52 100644
--- a/driver-csi.c
+++ b/driver-csi.c
@@ -221,12 +221,12 @@ handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
{
// rxvt protocol
key->type = TERMKEY_TYPE_MOUSE;
- key->code.mouse[0] = arg[0];
+ key->code.mouse.info = arg[0] - 0x20;
- key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
- key->code.mouse[0] &= ~0x1c;
+ key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
+ key->code.mouse.info &= ~0x1c;
- termkey_key_set_linecol (key, arg[1], arg[2]);
+ termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
return TERMKEY_RES_KEY;
}
@@ -234,15 +234,15 @@ handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
{
// SGR protocol
key->type = TERMKEY_TYPE_MOUSE;
- key->code.mouse[0] = arg[0];
+ key->code.mouse.info = arg[0];
- key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
- key->code.mouse[0] &= ~0x1c;
+ key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
+ key->code.mouse.info &= ~0x1c;
- termkey_key_set_linecol (key, arg[1], arg[2]);
+ termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
if (cmd == 'm') // release
- key->code.mouse[3] |= 0x80;
+ key->code.mouse.info |= 0x8000;
return TERMKEY_RES_KEY;
}
return TERMKEY_RES_NONE;
@@ -267,7 +267,7 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
return TERMKEY_RES_KEY;
int btn = 0;
- int code = key->code.mouse[0];
+ int code = key->code.mouse.info;
int drag = code & 0x20;
code &= ~0x3c;
@@ -297,7 +297,7 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
if (button)
*button = btn;
- if (key->code.mouse[3] & 0x80)
+ if (key->code.mouse.info & 0x8000)
*event = TERMKEY_MOUSE_RELEASE;
return TERMKEY_RES_KEY;
}
@@ -355,10 +355,9 @@ handle_csi_y (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
return TERMKEY_RES_NONE;
key->type = TERMKEY_TYPE_MODEREPORT;
- key->code.mouse[0] = (cmd >> 8);
- key->code.mouse[1] = arg[0] >> 8;
- key->code.mouse[2] = arg[0] & 0xff;
- key->code.mouse[3] = arg[1];
+ key->code.mode.initial = (cmd >> 8);
+ key->code.mode.mode = arg[0];
+ key->code.mode.value = arg[1];
return TERMKEY_RES_KEY;
default:
@@ -376,11 +375,11 @@ termkey_interpret_modereport (termkey_t *tk,
return TERMKEY_RES_NONE;
if (initial)
- *initial = key->code.mouse[0];
+ *initial = key->code.mode.initial;
if (mode)
- *mode = (key->code.mouse[1] << 8) | key->code.mouse[2];
+ *mode = key->code.mode.mode;
if (value)
- *value = key->code.mouse[3];
+ *value = key->code.mode.value;
return TERMKEY_RES_KEY;
}
@@ -616,7 +615,7 @@ peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
return TERMKEY_RES_KEY;
}
- // Mouse in X10 encoding consumes the next 3 bytes also
+ // Mouse in X10 encoding consumes the next 3 bytes also (or more with 1005)
if (cmd == 'M' && args < 3)
{
tk->buffstart += csi_len;
diff --git a/termkey2-internal.h b/termkey2-internal.h
index 3881865..5da33ff 100644
--- a/termkey2-internal.h
+++ b/termkey2-internal.h
@@ -86,26 +86,23 @@ static inline void
termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col)
{
if (col)
- *col = ((unsigned char) key->code.mouse[1]
- | ((unsigned char) key->code.mouse[3] & 0x0f) << 8) - 1;
+ *col = key->code.mouse.x;
if (line)
- *line = ((unsigned char) key->code.mouse[2]
- | ((unsigned char) key->code.mouse[3] & 0x70) << 4) - 1;
+ *line = key->code.mouse.y;
}
static inline void
termkey_key_set_linecol (termkey_key_t *key, int line, int col)
{
- if (++line > 0xfff)
- line = 0xfff;
+ if (line > UINT16_MAX)
+ line = UINT16_MAX;
- if (++col > 0x7ff)
- col = 0x7ff;
+ if (col > UINT16_MAX)
+ col = UINT16_MAX;
- key->code.mouse[1] = (line & 0x0ff);
- key->code.mouse[2] = (col & 0x0ff);
- key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
+ key->code.mouse.x = col;
+ key->code.mouse.y = line;
}
extern termkey_driver_t termkey_driver_csi;
diff --git a/termkey2.c b/termkey2.c
index e9b574c..37831b8 100644
--- a/termkey2.c
+++ b/termkey2.c
@@ -966,22 +966,121 @@ peekkey_simple (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep)
}
}
+// XXX: With the current infrastructure I'm not sure how to properly handle
+// this. peekkey() isn't made for skipping invalid inputs.
+#define INVALID_1005 0x20
+
+static termkey_result_t
+parse_1005_value (const unsigned char **bytes, size_t *len, uint32_t *cp)
+{
+ unsigned int nbytes;
+ unsigned char b0 = (*bytes)[0];
+ if (b0 < 0x80)
+ {
+ // Single byte ASCII
+ *cp = b0;
+ nbytes = 1;
+ goto end;
+ }
+ else if (b0 < 0xc0)
+ {
+ // Starts with a continuation byte - that's not right
+ *cp = INVALID_1005;
+ nbytes = 1;
+ goto end;
+ }
+ else if (b0 < 0xe0)
+ {
+ nbytes = 2;
+ *cp = b0 & 0x1f;
+ }
+ else if (b0 < 0xf0)
+ {
+ nbytes = 3;
+ *cp = b0 & 0x0f;
+ }
+ else if (b0 < 0xf8)
+ {
+ nbytes = 4;
+ *cp = b0 & 0x07;
+ }
+ else if (b0 < 0xfc)
+ {
+ nbytes = 5;
+ *cp = b0 & 0x03;
+ }
+ else if (b0 < 0xfe)
+ {
+ nbytes = 6;
+ *cp = b0 & 0x01;
+ }
+ else
+ {
+ *cp = INVALID_1005;
+ nbytes = 1;
+ goto end;
+ }
+
+ for (unsigned int b = 1; b < nbytes; b++)
+ {
+ if (b >= *len)
+ return TERMKEY_RES_AGAIN;
+
+ unsigned char cb = (*bytes)[b];
+ if (cb < 0x80 || cb >= 0xc0)
+ {
+ *cp = INVALID_1005;
+ nbytes = b;
+ goto end;
+ }
+ *cp <<= 6;
+ *cp |= cb & 0x3f;
+ }
+
+end:
+ (*bytes) += nbytes;
+ (*len) -= nbytes;
+ return TERMKEY_RES_KEY;
+}
+
static termkey_result_t
peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep)
{
- if (tk->buffcount < 3)
- return TERMKEY_RES_AGAIN;
+ uint32_t b, x, y;
+
+ // TODO: Add some API to switch on 1005 mode support
+ if (false)
+ {
+ const unsigned char *buff = tk->buffer + tk->buffstart;
+ size_t len = tk->buffcount;
+
+ if (parse_1005_value (&buff, &len, &b) == TERMKEY_RES_AGAIN
+ || parse_1005_value (&buff, &len, &x) == TERMKEY_RES_AGAIN
+ || parse_1005_value (&buff, &len, &y) == TERMKEY_RES_AGAIN)
+ return TERMKEY_RES_AGAIN;
+
+ *nbytep = tk->buffcount - len;
+ }
+ else
+ {
+ if (tk->buffcount < 3)
+ return TERMKEY_RES_AGAIN;
+
+ b = CHARAT (0);
+ x = CHARAT (1);
+ y = CHARAT (2);
+
+ *nbytep = 3;
+ }
key->type = TERMKEY_TYPE_MOUSE;
- key->code.mouse[0] = CHARAT (0) - 0x20;
- key->code.mouse[1] = CHARAT (1) - 0x20;
- key->code.mouse[2] = CHARAT (2) - 0x20;
- key->code.mouse[3] = 0;
+ key->code.mouse.info = b - 0x20;
+ key->code.mouse.x = x - 0x20 - 1;
+ key->code.mouse.y = y - 0x20 - 1;
- key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
- key->code.mouse[0] &= ~0x1c;
+ key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
+ key->code.mouse.info &= ~0x1c;
- *nbytep = 3;
return TERMKEY_RES_KEY;
}
@@ -1525,7 +1624,8 @@ termkey_keycmp (termkey_t *tk,
break;
case TERMKEY_TYPE_MOUSE:
{
- int cmp = strncmp (key1.code.mouse, key2.code.mouse, 4);
+ int cmp = memcmp (&key1.code.mouse, &key2.code.mouse,
+ sizeof key1.code.mouse);
if (cmp != 0)
return cmp;
break;
diff --git a/termkey2.h b/termkey2.h
index 60a3038..0fa0635 100644
--- a/termkey2.h
+++ b/termkey2.h
@@ -137,9 +137,14 @@ struct termkey_key
uint32_t codepoint; /* TERMKEY_TYPE_KEY */
int number; /* TERMKEY_TYPE_FUNCTION */
termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */
- // TODO: rewrite this insanity
- char mouse[4]; /* TERMKEY_TYPE_MOUSE */
- /* opaque, see termkey_interpret_mouse() */
+
+ /* TERMKEY_TYPE_MODEREPORT */
+ /* opaque, see termkey_interpret_modereport() */
+ struct { char initial; int mode, value; } mode;
+
+ /* TERMKEY_TYPE_MOUSE */
+ /* opaque, see termkey_interpret_mouse() */
+ struct { uint16_t x, y, info; } mouse;
} code;
int modifiers;
--
cgit v1.2.3-70-g09d2