diff --git a/driver-csi.c b/driver-csi.c index 1719e70..d305356 100644 --- a/driver-csi.c +++ b/driver-csi.c @@ -187,6 +187,21 @@ static TermKeyResult handle_csi_mouse(TermKey *tk, TermKeyKey *key, int cmd, lon return TERMKEY_RES_NONE; } +/* + * Handler for CSI R position reports + */ + +static TermKeyResult handle_csi_position(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +{ + if(args < 2) + return TERMKEY_RES_NONE; + + key->type = TERMKEY_TYPE_POSITION; + termkey_key_set_linecol(key, arg[0], arg[1]); + + return TERMKEY_RES_KEY; +} + static int register_keys(void) { int i; @@ -268,6 +283,8 @@ static int register_keys(void) csi_handlers['M' - 0x40] = &handle_csi_mouse; csi_handlers['m' - 0x40] = &handle_csi_mouse; + csi_handlers['R' - 0x40] = &handle_csi_position; + keyinfo_initialised = 1; return 1; } diff --git a/t/31position.c b/t/31position.c new file mode 100644 index 0000000..baefb8b --- /dev/null +++ b/t/31position.c @@ -0,0 +1,28 @@ +#include "../termkey.h" +#include "taplib.h" + +int main(int argc, char *argv[]) +{ + TermKey *tk; + TermKeyKey key; + int line, col; + + plan_tests(5); + + tk = termkey_new_abstract("vt100", 0); + + termkey_push_bytes(tk, "\e[15;7R", 7); + + is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for position report"); + + is_int(key.type, TERMKEY_TYPE_POSITION, "key.type for position report"); + + is_int(termkey_interpret_position(tk, &key, &line, &col), TERMKEY_RES_KEY, "interpret_position yields RES_KEY"); + + is_int(line, 7, "line for position report"); + is_int(col, 15, "column for position report"); + + termkey_destroy(tk); + + return exit_status(); +} diff --git a/termkey.c b/termkey.c index ade90a8..e080fec 100644 --- a/termkey.c +++ b/termkey.c @@ -956,6 +956,16 @@ TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKe return TERMKEY_RES_KEY; } +TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col) +{ + if(key->type != TERMKEY_TYPE_POSITION) + return TERMKEY_RES_NONE; + + termkey_key_get_linecol(key, line, col); + + return TERMKEY_RES_KEY; +} + TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key) { size_t nbytes = 0; @@ -1297,6 +1307,9 @@ size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, T } } break; + case TERMKEY_TYPE_POSITION: + l = snprintf(buffer + pos, len - pos, "Position"); + break; } if(l <= 0) return pos; @@ -1394,18 +1407,32 @@ int termkey_keycmp(TermKey *tk, const TermKeyKey *key1p, const TermKeyKey *key2p case TERMKEY_TYPE_UNICODE: if(key1.code.codepoint != key2.code.codepoint) return key1.code.codepoint - key2.code.codepoint; + break; case TERMKEY_TYPE_KEYSYM: if(key1.code.sym != key2.code.sym) return key1.code.sym - key2.code.sym; + break; case TERMKEY_TYPE_FUNCTION: if(key1.code.number != key2.code.number) return key1.code.number - key2.code.number; + break; case TERMKEY_TYPE_MOUSE: { int cmp = strncmp(key1.code.mouse, key2.code.mouse, 4); if(cmp != 0) return cmp; } + break; + case TERMKEY_TYPE_POSITION: + { + int line1, col1, line2, col2; + termkey_interpret_position(tk, &key1, &line1, &col1); + termkey_interpret_position(tk, &key2, &line2, &col2); + if(line1 != line2) + return line1 - line2; + return col1 - col2; + } + break; } return key1.modifiers - key2.modifiers; diff --git a/termkey.h.in b/termkey.h.in index 6c91b09..bd5187c 100644 --- a/termkey.h.in +++ b/termkey.h.in @@ -95,7 +95,8 @@ typedef enum { TERMKEY_TYPE_UNICODE, TERMKEY_TYPE_FUNCTION, TERMKEY_TYPE_KEYSYM, - TERMKEY_TYPE_MOUSE + TERMKEY_TYPE_MOUSE, + TERMKEY_TYPE_POSITION } TermKeyType; typedef enum { @@ -199,6 +200,8 @@ TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname); TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col); +TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col); + typedef enum { TERMKEY_FORMAT_LONGMOD = 1 << 0, /* Shift-... instead of S-... */ TERMKEY_FORMAT_CARETCTRL = 1 << 1, /* ^X instead of C-X */