2015-04-23 00:15:19 +00:00
|
|
|
// 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)
|
|
|
|
{
|
2015-04-23 02:28:44 +00:00
|
|
|
int n = 0;
|
|
|
|
while (*s2 && n < len) {
|
|
|
|
if (*s1++ != *s2++)
|
|
|
|
return false;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
return *s2 == 0;
|
2015-04-23 00:15:19 +00:00
|
|
|
}
|
|
|
|
|
2015-08-10 03:01:42 +00:00
|
|
|
#define FOO(...) { \
|
|
|
|
FILE* f = fopen("log", "a+"); \
|
|
|
|
fprintf(f, __VA_ARGS__); \
|
|
|
|
fclose(f); \
|
|
|
|
}
|
|
|
|
|
2015-04-23 00:15:19 +00:00
|
|
|
// 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)
|
|
|
|
{
|
2015-09-04 18:07:08 +00:00
|
|
|
static int parse_attempts = 0;
|
|
|
|
static const int MAX_PARSE_ATTEMPTS = 2;
|
|
|
|
|
2015-08-10 03:01:42 +00:00
|
|
|
//? int x = 0;
|
|
|
|
//? FOO("-- %d\n", len);
|
|
|
|
//? for (x = 0; x < len; ++x) {
|
|
|
|
//? FOO("%d\n", (unsigned char)buf[x]);
|
|
|
|
//? }
|
2015-04-23 02:28:44 +00:00
|
|
|
if (len >= 6 && starts_with(buf, len, "\033[M")) {
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
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:
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-04-23 02:28:44 +00:00
|
|
|
return -6;
|
|
|
|
}
|
|
|
|
event->type = TB_EVENT_MOUSE; // TB_EVENT_KEY by default
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// the coord is 1,1 for upper left
|
2015-05-09 15:56:12 +00:00
|
|
|
event->x = (uint8_t)buf[4] - 1 - 32;
|
|
|
|
event->y = (uint8_t)buf[5] - 1 - 32;
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-04-23 02:28:44 +00:00
|
|
|
return 6;
|
|
|
|
}
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// 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;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-04-23 02:28:44 +00:00
|
|
|
return strlen(keys[i]);
|
|
|
|
}
|
|
|
|
}
|
2015-08-10 03:01:42 +00:00
|
|
|
|
|
|
|
if (starts_with(buf, len, "\033[200~")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_START_PASTE;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-08-10 03:01:42 +00:00
|
|
|
return strlen("\033[200~");
|
|
|
|
}
|
|
|
|
if (starts_with(buf, len, "\033[201~")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_END_PASTE;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-08-10 03:01:42 +00:00
|
|
|
return strlen("\033[201~");
|
|
|
|
}
|
2015-09-03 02:18:24 +00:00
|
|
|
if (starts_with(buf, len, "\033[1;5A")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_CTRL_ARROW_UP;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-09-03 02:18:24 +00:00
|
|
|
return strlen("\033[1;5A");
|
|
|
|
}
|
|
|
|
if (starts_with(buf, len, "\033[1;5B")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_CTRL_ARROW_DOWN;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-09-03 02:18:24 +00:00
|
|
|
return strlen("\033[1;5B");
|
|
|
|
}
|
|
|
|
if (starts_with(buf, len, "\033[1;5C")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_CTRL_ARROW_RIGHT;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-09-03 02:18:24 +00:00
|
|
|
return strlen("\033[1;5C");
|
|
|
|
}
|
|
|
|
if (starts_with(buf, len, "\033[1;5D")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_CTRL_ARROW_LEFT;
|
2015-09-04 18:07:08 +00:00
|
|
|
parse_attempts = 0;
|
2015-09-03 02:18:24 +00:00
|
|
|
return strlen("\033[1;5D");
|
|
|
|
}
|
2015-09-11 16:05:22 +00:00
|
|
|
if (starts_with(buf, len, "\033[Z")) {
|
|
|
|
event->ch = 0;
|
|
|
|
event->key = TB_KEY_SHIFT_TAB;
|
|
|
|
parse_attempts = 0;
|
|
|
|
return strlen("\033[Z");
|
|
|
|
}
|
2015-08-10 03:01:42 +00:00
|
|
|
|
2015-09-04 18:07:08 +00:00
|
|
|
// 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;
|
2015-04-23 00:15:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-23 03:39:43 +00:00
|
|
|
static bool extract_event(struct tb_event *event, struct bytebuffer *inbuf)
|
2015-04-23 00:15:19 +00:00
|
|
|
{
|
2015-04-23 02:28:44 +00:00
|
|
|
const char *buf = inbuf->buf;
|
|
|
|
const int len = inbuf->len;
|
|
|
|
if (len == 0)
|
|
|
|
return false;
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-08-10 03:01:42 +00:00
|
|
|
//? int x = 0;
|
|
|
|
//? FOO("== %d\n", len);
|
|
|
|
//? for (x = 0; x < len; ++x) {
|
|
|
|
//? FOO("%x\n", (unsigned char)buf[x]);
|
|
|
|
//? }
|
2015-04-23 02:28:44 +00:00
|
|
|
if (buf[0] == '\033') {
|
|
|
|
int n = parse_escape_seq(event, buf, len);
|
2015-09-04 18:07:08 +00:00
|
|
|
if (n == 0) return false;
|
2015-09-03 02:18:24 +00:00
|
|
|
//? FOO("parsed: %u %u %u %u\n", n, (unsigned int)event->type, (unsigned int)event->key, event->ch);
|
2015-09-04 18:07:08 +00:00
|
|
|
bool success = true;
|
|
|
|
if (n < 0) {
|
|
|
|
success = false;
|
|
|
|
n = -n;
|
2015-04-23 02:28:44 +00:00
|
|
|
}
|
2015-09-04 18:07:08 +00:00
|
|
|
bytebuffer_truncate(inbuf, n);
|
|
|
|
return success;
|
2015-04-23 02:28:44 +00:00
|
|
|
}
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// 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
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// feh... we got utf8 here
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2015-04-23 00:15:19 +00:00
|
|
|
|
2015-04-23 02:28:44 +00:00
|
|
|
// event isn't recognized, perhaps there is not enough bytes in utf8
|
|
|
|
// sequence
|
|
|
|
return false;
|
2015-04-23 00:15:19 +00:00
|
|
|
}
|