about summary refs log tree commit diff stats
path: root/cpp/termbox/input.inl
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-22 17:15:19 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-22 17:15:19 -0700
commit5f1285238b09a5f01836138f5bb94654f78588a7 (patch)
tree167153b6944af30fc25c3097f25b16f658e5bd8a /cpp/termbox/input.inl
parente89eaad3410cf513c5235ff45db60bf994fbb104 (diff)
downloadmu-5f1285238b09a5f01836138f5bb94654f78588a7.tar.gz
1136 - switch from ncurses to https://github.com/nsf/termbox
Diffstat (limited to 'cpp/termbox/input.inl')
-rw-r--r--cpp/termbox/input.inl132
1 files changed, 132 insertions, 0 deletions
diff --git a/cpp/termbox/input.inl b/cpp/termbox/input.inl
new file mode 100644
index 00000000..8c555114
--- /dev/null
+++ b/cpp/termbox/input.inl
@@ -0,0 +1,132 @@
+// 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;
+}
+
+// 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)
+{
+	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:
+			return -6;
+		}
+		event->type = TB_EVENT_MOUSE; // TB_EVENT_KEY by default
+
+		// the coord is 1,1 for upper left
+		event->x = buf[4] - 1 - 32;
+		event->y = buf[5] - 1 - 32;
+
+		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;
+			return strlen(keys[i]);
+		}
+	}
+	return 0;
+}
+
+static bool extract_event(struct tb_event *event, struct bytebuffer *inbuf, int inputmode)
+{
+	const char *buf = inbuf->buf;
+	const int len = inbuf->len;
+	if (len == 0)
+		return false;
+
+	if (buf[0] == '\033') {
+		int n = parse_escape_seq(event, buf, len);
+		if (n != 0) {
+			bool success = true;
+			if (n < 0) {
+				success = false;
+				n = -n;
+			}
+			bytebuffer_truncate(inbuf, n);
+			return success;
+		} else {
+			// it's not escape sequence, then it's ALT or ESC,
+			// check inputmode
+			if (inputmode&TB_INPUT_ESC) {
+				// if we're in escape mode, fill ESC event, pop
+				// buffer, return success
+				event->ch = 0;
+				event->key = TB_KEY_ESC;
+				event->mod = 0;
+				bytebuffer_truncate(inbuf, 1);
+				return true;
+			}
+			if (inputmode&TB_INPUT_ALT) {
+				// if we're in alt mode, set ALT modifier to
+				// event and redo parsing
+				event->mod = TB_MOD_ALT;
+				bytebuffer_truncate(inbuf, 1);
+				return extract_event(event, inbuf, inputmode);
+			}
+			assert(!"never got here");
+		}
+	}
+
+	// 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;
+}