diff options
Diffstat (limited to 'archive/2.vm/termbox/input.inl')
-rw-r--r-- | archive/2.vm/termbox/input.inl | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/archive/2.vm/termbox/input.inl b/archive/2.vm/termbox/input.inl new file mode 100644 index 00000000..83b4bb8c --- /dev/null +++ b/archive/2.vm/termbox/input.inl @@ -0,0 +1,185 @@ +// if s1 starts with s2 returns true, else false +// len is the length of s1 +// s2 should be null-terminated +static bool starts_with(const char *s1, int len, const char *s2) +{ + int n = 0; + while (*s2 && n < len) { + if (*s1++ != *s2++) + return false; + n++; + } + return *s2 == 0; +} + +#define FOO(...) { \ + FILE* f = fopen("log", "a+"); \ + fprintf(f, __VA_ARGS__); \ + fclose(f); \ +} + +// convert escape sequence to event, and return consumed bytes on success (failure == 0) +static int parse_escape_seq(struct tb_event *event, const char *buf, int len) +{ + static int parse_attempts = 0; + static const int MAX_PARSE_ATTEMPTS = 2; + +//? int x = 0; +//? FOO("-- %d\n", len); +//? for (x = 0; x < len; ++x) { +//? FOO("%d\n", (unsigned char)buf[x]); +//? } + if (len >= 6 && starts_with(buf, len, "\033[M")) { + + switch (buf[3] & 3) { + case 0: + if (buf[3] == 0x60) + event->key = TB_KEY_MOUSE_WHEEL_UP; + else + event->key = TB_KEY_MOUSE_LEFT; + break; + case 1: + if (buf[3] == 0x61) + event->key = TB_KEY_MOUSE_WHEEL_DOWN; + else + event->key = TB_KEY_MOUSE_MIDDLE; + break; + case 2: + event->key = TB_KEY_MOUSE_RIGHT; + break; + case 3: + event->key = TB_KEY_MOUSE_RELEASE; + break; + default: + parse_attempts = 0; + return -6; + } + event->type = TB_EVENT_MOUSE; // TB_EVENT_KEY by default + + // the coord is 1,1 for upper left + event->x = (uint8_t)buf[4] - 1 - 32; + event->y = (uint8_t)buf[5] - 1 - 32; + + parse_attempts = 0; + return 6; + } + + // it's pretty simple here, find 'starts_with' match and return + // success, else return failure + int i; + for (i = 0; keys[i]; i++) { + if (starts_with(buf, len, keys[i])) { + event->ch = 0; + event->key = 0xFFFF-i; + parse_attempts = 0; + return strlen(keys[i]); + } + } + + if (starts_with(buf, len, "\033[200~")) { + event->ch = 0; + event->key = TB_KEY_START_PASTE; + parse_attempts = 0; + return strlen("\033[200~"); + } + if (starts_with(buf, len, "\033[201~")) { + event->ch = 0; + event->key = TB_KEY_END_PASTE; + parse_attempts = 0; + return strlen("\033[201~"); + } + if (starts_with(buf, len, "\033[1;5A")) { + event->ch = 0; + event->key = TB_KEY_CTRL_ARROW_UP; + parse_attempts = 0; + return strlen("\033[1;5A"); + } + if (starts_with(buf, len, "\033[1;5B")) { + event->ch = 0; + event->key = TB_KEY_CTRL_ARROW_DOWN; + parse_attempts = 0; + return strlen("\033[1;5B"); + } + if (starts_with(buf, len, "\033[1;5C")) { + event->ch = 0; + event->key = TB_KEY_CTRL_ARROW_RIGHT; + parse_attempts = 0; + return strlen("\033[1;5C"); + } + if (starts_with(buf, len, "\033[1;5D")) { + event->ch = 0; + event->key = TB_KEY_CTRL_ARROW_LEFT; + parse_attempts = 0; + return strlen("\033[1;5D"); + } + if (starts_with(buf, len, "\033[Z")) { + event->ch = 0; + event->key = TB_KEY_SHIFT_TAB; + parse_attempts = 0; + return strlen("\033[Z"); + } + + // no escape sequence recognized? wait a bit in case our buffer is incomplete + ++parse_attempts; + if (parse_attempts < MAX_PARSE_ATTEMPTS) return 0; + // still nothing? give up and consume just the esc + event->ch = 0; + event->key = TB_KEY_ESC; + parse_attempts = 0; + return 1; +} + +static bool extract_event(struct tb_event *event, struct bytebuffer *inbuf) +{ + const char *buf = inbuf->buf; + const int len = inbuf->len; + if (len == 0) + return false; + +//? int x = 0; +//? FOO("== %d\n", len); +//? for (x = 0; x < len; ++x) { +//? FOO("%x\n", (unsigned char)buf[x]); +//? } + if (buf[0] == '\033') { + int n = parse_escape_seq(event, buf, len); + if (n == 0) return false; +//? FOO("parsed: %u %u %u %u\n", n, (unsigned int)event->type, (unsigned int)event->key, event->ch); + bool success = true; + if (n < 0) { + success = false; + n = -n; + } + bytebuffer_truncate(inbuf, n); + return success; + } + + // if we're here, this is not an escape sequence and not an alt sequence + // so, it's a FUNCTIONAL KEY or a UNICODE character + + // first of all check if it's a functional key + if ((unsigned char)buf[0] <= TB_KEY_SPACE || + (unsigned char)buf[0] == TB_KEY_BACKSPACE2) + { + // fill event, pop buffer, return success */ + event->ch = 0; + event->key = (uint16_t)buf[0]; + bytebuffer_truncate(inbuf, 1); + return true; + } + + // feh... we got utf8 here + + // check if there is all bytes + if (len >= tb_utf8_char_length(buf[0])) { + /* everything ok, fill event, pop buffer, return success */ + tb_utf8_char_to_unicode(&event->ch, buf); + event->key = 0; + bytebuffer_truncate(inbuf, tb_utf8_char_length(buf[0])); + return true; + } + + // event isn't recognized, perhaps there is not enough bytes in utf8 + // sequence + return false; +} |