|
@@ -5,6 +5,7 @@
|
|
|
#include <termios.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
+#include "core/Logger.h"
|
|
|
#include "core/Unicode.h"
|
|
|
|
|
|
#define ESC "\33["
|
|
@@ -12,6 +13,78 @@
|
|
|
|
|
|
static struct termios originalTerminal;
|
|
|
|
|
|
+typedef struct {
|
|
|
+ const u8* path;
|
|
|
+ u64 mapping;
|
|
|
+} EscapeSequence;
|
|
|
+
|
|
|
+#define K_CTRL TERMINAL_KEY_CTRL
|
|
|
+#define K_SHIFT TERMINAL_KEY_SHIFT
|
|
|
+#define K_ALT TERMINAL_KEY_ALT
|
|
|
+
|
|
|
+#define KEY_WITH_MODIFIER(c, m, n) {c, m | TERMINAL_KEY_##n}
|
|
|
+#define KEYS_WITH_MODIFIER(c, m) \
|
|
|
+ {u8"[1;" c "A", m | TERMINAL_KEY_ARROW_UP}, \
|
|
|
+ {u8"[1;" c "B", m | TERMINAL_KEY_ARROW_DOWN}, \
|
|
|
+ {u8"[1;" c "C", m | TERMINAL_KEY_ARROW_RIGHT}, \
|
|
|
+ {u8"[1;" c "D", m | TERMINAL_KEY_ARROW_LEFT}, \
|
|
|
+ {u8"[3;" c "~", m | TERMINAL_KEY_DELETE}, \
|
|
|
+ {u8"[1;" c "P", m | TERMINAL_KEY_F1}, \
|
|
|
+ {u8"[1;" c "Q", m | TERMINAL_KEY_F2}, \
|
|
|
+ {u8"[1;" c "R", m | TERMINAL_KEY_F3}, \
|
|
|
+ {u8"[1;" c "S", m | TERMINAL_KEY_F4}, \
|
|
|
+ {u8"[15;" c "~", m | TERMINAL_KEY_F5}, \
|
|
|
+ {u8"[17;" c "~", m | TERMINAL_KEY_F6}, \
|
|
|
+ {u8"[18;" c "~", m | TERMINAL_KEY_F7}, \
|
|
|
+ {u8"[19;" c "~", m | TERMINAL_KEY_F8}, \
|
|
|
+ {u8"[20;" c "~", m | TERMINAL_KEY_F9}, \
|
|
|
+ {u8"[21;" c "~", m | TERMINAL_KEY_F10}, \
|
|
|
+ {u8"[23;" c "~", m | TERMINAL_KEY_F11}, \
|
|
|
+ {u8"[24;" c "~", m | TERMINAL_KEY_F12}, \
|
|
|
+ {u8"[5;" c "~", m | TERMINAL_KEY_PAGE_UP}, \
|
|
|
+ {u8"[6;" c "~", m | TERMINAL_KEY_PAGE_DOWN}, \
|
|
|
+ {u8"[1;" c "H", m | TERMINAL_KEY_HOME}, { \
|
|
|
+ u8"[1;" c "F", m | TERMINAL_KEY_END \
|
|
|
+ }
|
|
|
+
|
|
|
+static const EscapeSequence ESCAPE_SEQUENCES[] = {
|
|
|
+ {u8"[A", TERMINAL_KEY_ARROW_UP},
|
|
|
+ {u8"[B", TERMINAL_KEY_ARROW_DOWN},
|
|
|
+ {u8"[C", TERMINAL_KEY_ARROW_RIGHT},
|
|
|
+ {u8"[D", TERMINAL_KEY_ARROW_LEFT},
|
|
|
+ {u8"[3~", TERMINAL_KEY_DELETE},
|
|
|
+ {u8"OP", TERMINAL_KEY_F1},
|
|
|
+ {u8"[[A", TERMINAL_KEY_F1},
|
|
|
+ {u8"OQ", TERMINAL_KEY_F2},
|
|
|
+ {u8"[[B", TERMINAL_KEY_F2},
|
|
|
+ {u8"OR", TERMINAL_KEY_F3},
|
|
|
+ {u8"[[C", TERMINAL_KEY_F3},
|
|
|
+ {u8"OS", TERMINAL_KEY_F4},
|
|
|
+ {u8"[[D", TERMINAL_KEY_F4},
|
|
|
+ {u8"[15~", TERMINAL_KEY_F5},
|
|
|
+ {u8"[[E", TERMINAL_KEY_F5},
|
|
|
+ {u8"[17~", TERMINAL_KEY_F6},
|
|
|
+ {u8"[18~", TERMINAL_KEY_F7},
|
|
|
+ {u8"[19~", TERMINAL_KEY_F8},
|
|
|
+ {u8"[20~", TERMINAL_KEY_F9},
|
|
|
+ {u8"[21~", TERMINAL_KEY_F10},
|
|
|
+ {u8"[23~", TERMINAL_KEY_F11},
|
|
|
+ {u8"[24~", TERMINAL_KEY_F12},
|
|
|
+ {u8"[5~", TERMINAL_KEY_PAGE_UP},
|
|
|
+ {u8"[6~", TERMINAL_KEY_PAGE_DOWN},
|
|
|
+ {u8"[H", TERMINAL_KEY_HOME},
|
|
|
+ {u8"[1~", TERMINAL_KEY_HOME},
|
|
|
+ {u8"[F", TERMINAL_KEY_END},
|
|
|
+ {u8"[4~", TERMINAL_KEY_END},
|
|
|
+ KEYS_WITH_MODIFIER("2", K_SHIFT),
|
|
|
+ KEYS_WITH_MODIFIER("3", K_ALT),
|
|
|
+ KEYS_WITH_MODIFIER("4", K_ALT | K_SHIFT),
|
|
|
+ KEYS_WITH_MODIFIER("5", K_CTRL),
|
|
|
+ KEYS_WITH_MODIFIER("6", K_CTRL | K_SHIFT),
|
|
|
+ KEYS_WITH_MODIFIER("7", K_CTRL | K_ALT),
|
|
|
+ KEYS_WITH_MODIFIER("8", K_CTRL | K_ALT | K_SHIFT),
|
|
|
+};
|
|
|
+
|
|
|
void enterAlternativeTerminal() {
|
|
|
esc("?1049h");
|
|
|
}
|
|
@@ -86,21 +159,40 @@ static u8 readChar() {
|
|
|
return bytes <= 0 ? '\0' : c;
|
|
|
}
|
|
|
|
|
|
+static bool couldMatch(const u8* s, const u8* e, size_t l) {
|
|
|
+ while(l > 0 && *s != 0 && *e != 0 && *s == *e) {
|
|
|
+ s++;
|
|
|
+ e++;
|
|
|
+ l--;
|
|
|
+ }
|
|
|
+ return l == 0;
|
|
|
+}
|
|
|
+
|
|
|
static u64 readEscapeSequence() {
|
|
|
- if(readChar() != '[') {
|
|
|
- return TERMINAL_KEY_UNKNOWN;
|
|
|
+ u8 s[10] = {0};
|
|
|
+ s[0] = readChar();
|
|
|
+ s[1] = readChar();
|
|
|
+ if(s[1] == 0) {
|
|
|
+ return s[0] | K_ALT;
|
|
|
}
|
|
|
- switch(readChar()) {
|
|
|
- case 'A': return TERMINAL_KEY_ARROW_UP;
|
|
|
- case 'B': return TERMINAL_KEY_ARROW_DOWN;
|
|
|
- case 'C': return TERMINAL_KEY_ARROW_RIGHT;
|
|
|
- case 'D': return TERMINAL_KEY_ARROW_LEFT;
|
|
|
- case '3':
|
|
|
- if(readChar() == '~') {
|
|
|
- return TERMINAL_KEY_DELETE;
|
|
|
+ size_t l = 2;
|
|
|
+ while(true) {
|
|
|
+ bool matchFound = false;
|
|
|
+ for(size_t i = 0; i < ARRAY_LENGTH(ESCAPE_SEQUENCES); i++) {
|
|
|
+ const EscapeSequence* e = ESCAPE_SEQUENCES + i;
|
|
|
+ if(couldMatch(s, e->path, l)) {
|
|
|
+ matchFound = true;
|
|
|
+ if(e->path[l] == 0) {
|
|
|
+ return e->mapping;
|
|
|
+ }
|
|
|
}
|
|
|
+ }
|
|
|
+ if(!matchFound || l >= ARRAY_LENGTH(s)) {
|
|
|
break;
|
|
|
+ }
|
|
|
+ s[l++] = readChar();
|
|
|
}
|
|
|
+ LOG_WARNING("Unknown escape sequence starting with '%s'", s);
|
|
|
return TERMINAL_KEY_UNKNOWN;
|
|
|
}
|
|
|
|
|
@@ -121,3 +213,16 @@ u64 getRawChar() {
|
|
|
}
|
|
|
return c;
|
|
|
}
|
|
|
+
|
|
|
+bool isSpecialChar(u64 u) {
|
|
|
+ return u >= TERMINAL_KEY_UNKNOWN;
|
|
|
+}
|
|
|
+
|
|
|
+SpecialChar convertToSpecialChar(u64 u) {
|
|
|
+ SpecialChar c = {0};
|
|
|
+ c.shift = TERMINAL_KEY_SHIFT & u;
|
|
|
+ c.control = TERMINAL_KEY_CTRL & u;
|
|
|
+ c.alt = TERMINAL_KEY_ALT & u;
|
|
|
+ c.key = u & 0x1'FFFF'FFFF;
|
|
|
+ return c;
|
|
|
+}
|