From e330d751a42def1e014227d5e39969af6e87591f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Mon, 13 Oct 2014 23:36:14 +0200 Subject: [PATCH] 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;