|
@@ -1,22 +1,24 @@
|
|
|
#include "core/Terminal.hpp"
|
|
|
|
|
|
-#include <stdio.h>
|
|
|
+#include <cstdio>
|
|
|
+
|
|
|
#include <sys/ioctl.h>
|
|
|
#include <termios.h>
|
|
|
#include <unistd.h>
|
|
|
|
|
|
+#include "core/Array.hpp"
|
|
|
#include "core/Logger.hpp"
|
|
|
#include "core/Unicode.hpp"
|
|
|
|
|
|
#define ESC "\33["
|
|
|
#define esc(s) fputs(ESC s, stdout)
|
|
|
|
|
|
-static struct termios originalTerminal;
|
|
|
+static termios originalTerminal;
|
|
|
|
|
|
-typedef struct {
|
|
|
- const u8* path;
|
|
|
- u64 mapping;
|
|
|
-} EscapeSequence;
|
|
|
+struct EscapeSequence {
|
|
|
+ const u8 path[16] = {};
|
|
|
+ u64 mapping = 0;
|
|
|
+};
|
|
|
|
|
|
#define K_CTRL TERMINAL_KEY_CTRL
|
|
|
#define K_SHIFT TERMINAL_KEY_SHIFT
|
|
@@ -47,7 +49,7 @@ typedef struct {
|
|
|
u8"[1;" c "F", m | TERMINAL_KEY_END \
|
|
|
}
|
|
|
|
|
|
-static const EscapeSequence ESCAPE_SEQUENCES[] = {
|
|
|
+static const Core::Array<EscapeSequence, 175> ESCAPE_SEQUENCES = {{
|
|
|
{u8"[A", TERMINAL_KEY_ARROW_UP},
|
|
|
{u8"[B", TERMINAL_KEY_ARROW_DOWN},
|
|
|
{u8"[C", TERMINAL_KEY_ARROW_RIGHT},
|
|
@@ -83,73 +85,73 @@ static const EscapeSequence ESCAPE_SEQUENCES[] = {
|
|
|
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() {
|
|
|
+void Core::enterAlternativeTerminal() {
|
|
|
esc("?1049h");
|
|
|
}
|
|
|
|
|
|
-void leaveAlternativeTerminal() {
|
|
|
+void Core::leaveAlternativeTerminal() {
|
|
|
esc("?1049l");
|
|
|
}
|
|
|
|
|
|
-void clearTerminal() {
|
|
|
+void Core::clearTerminal() {
|
|
|
esc("2J");
|
|
|
}
|
|
|
|
|
|
-IntVector2 getTerminalSize() {
|
|
|
- struct winsize w;
|
|
|
+Core::IntVector2 Core::getTerminalSize() {
|
|
|
+ winsize w;
|
|
|
if(ioctl(0, TIOCGWINSZ, &w)) {
|
|
|
- return IV(0, 0);
|
|
|
+ return IntVector2(0, 0);
|
|
|
}
|
|
|
- return IV(w.ws_col, w.ws_row);
|
|
|
+ return IntVector2(w.ws_col, w.ws_row);
|
|
|
}
|
|
|
|
|
|
-void clearTerminalLine() {
|
|
|
+void Core::clearTerminalLine() {
|
|
|
esc("2K\r");
|
|
|
}
|
|
|
|
|
|
-void hideCursor() {
|
|
|
+void Core::hideCursor() {
|
|
|
esc("?25l");
|
|
|
}
|
|
|
|
|
|
-void showCursor() {
|
|
|
+void Core::showCursor() {
|
|
|
esc("?25h");
|
|
|
}
|
|
|
|
|
|
-void resetCursor() {
|
|
|
+void Core::resetCursor() {
|
|
|
esc("H");
|
|
|
}
|
|
|
|
|
|
-void moveCursorLeft(int i) {
|
|
|
+void Core::moveCursorLeft(int i) {
|
|
|
printf(ESC "%dD", i);
|
|
|
}
|
|
|
|
|
|
-void moveCursorRight(int i) {
|
|
|
+void Core::moveCursorRight(int i) {
|
|
|
printf(ESC "%dC", i);
|
|
|
}
|
|
|
|
|
|
-void moveCursorUp(int i) {
|
|
|
+void Core::moveCursorUp(int i) {
|
|
|
printf(ESC "%dA", i);
|
|
|
}
|
|
|
|
|
|
-void moveCursorDown(int i) {
|
|
|
+void Core::moveCursorDown(int i) {
|
|
|
printf(ESC "%dB", i);
|
|
|
}
|
|
|
|
|
|
-bool enterRawTerminal() {
|
|
|
+bool Core::enterRawTerminal() {
|
|
|
if(tcgetattr(STDIN_FILENO, &originalTerminal)) {
|
|
|
return true;
|
|
|
}
|
|
|
- struct termios raw = originalTerminal;
|
|
|
- raw.c_iflag &= ~(tcflag_t)(ICRNL | IXON);
|
|
|
- raw.c_lflag &= ~(tcflag_t)(ECHO | ICANON | IEXTEN | ISIG);
|
|
|
+ termios raw = originalTerminal;
|
|
|
+ raw.c_iflag &= ~static_cast<tcflag_t>(ICRNL | IXON);
|
|
|
+ raw.c_lflag &= ~static_cast<tcflag_t>(ECHO | ICANON | IEXTEN | ISIG);
|
|
|
raw.c_cc[VMIN] = 0;
|
|
|
raw.c_cc[VTIME] = 0;
|
|
|
return tcsetattr(STDIN_FILENO, TCSANOW, &raw);
|
|
|
}
|
|
|
|
|
|
-bool leaveRawTerminal() {
|
|
|
+bool Core::leaveRawTerminal() {
|
|
|
return tcsetattr(STDIN_FILENO, TCSAFLUSH, &originalTerminal);
|
|
|
}
|
|
|
|
|
@@ -169,7 +171,8 @@ static bool couldMatch(const u8* s, const u8* e, size_t l) {
|
|
|
}
|
|
|
|
|
|
static u64 readEscapeSequence() {
|
|
|
- u8 s[10] = {0};
|
|
|
+ constexpr size_t CHARS = 10;
|
|
|
+ u8 s[CHARS] = {0};
|
|
|
s[0] = readChar();
|
|
|
s[1] = readChar();
|
|
|
if(s[1] == 0) {
|
|
@@ -178,35 +181,35 @@ static u64 readEscapeSequence() {
|
|
|
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)) {
|
|
|
+ for(size_t i = 0; i < ESCAPE_SEQUENCES.getLength(); i++) {
|
|
|
+ const EscapeSequence& e = ESCAPE_SEQUENCES[i];
|
|
|
+ if(couldMatch(s, e.path, l)) {
|
|
|
matchFound = true;
|
|
|
- if(e->path[l] == 0) {
|
|
|
- return e->mapping;
|
|
|
+ if(e.path[l] == 0) {
|
|
|
+ return e.mapping;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if(!matchFound || l >= ARRAY_LENGTH(s)) {
|
|
|
+ if(!matchFound || l >= CHARS) {
|
|
|
break;
|
|
|
}
|
|
|
s[l++] = readChar();
|
|
|
}
|
|
|
- REPORT(LOG_WARNING, "Unknown escape sequence starting with '%s'", s);
|
|
|
+ REPORT(LogLevel::WARNING, "Unknown escape sequence starting with '#'", s);
|
|
|
return TERMINAL_KEY_UNKNOWN;
|
|
|
}
|
|
|
|
|
|
static u64 readUTF8() {
|
|
|
- UTF8 u = {0};
|
|
|
+ Core::UTF8 u = {};
|
|
|
u.data[0] = readChar();
|
|
|
- u.length = getUTF8Length(u.data[0]);
|
|
|
+ u.length = Core::getUTF8Length(u.data[0]);
|
|
|
for(u32 i = 1; i < u.length; i++) {
|
|
|
u.data[i] = readChar();
|
|
|
}
|
|
|
return convertUTF8toUnicode(u);
|
|
|
}
|
|
|
|
|
|
-u64 getRawChar() {
|
|
|
+u64 Core::getRawChar() {
|
|
|
u64 c = readUTF8();
|
|
|
if(c == 27) {
|
|
|
return readEscapeSequence();
|
|
@@ -214,12 +217,12 @@ u64 getRawChar() {
|
|
|
return c;
|
|
|
}
|
|
|
|
|
|
-bool isSpecialChar(u64 u) {
|
|
|
+bool Core::isSpecialChar(u64 u) {
|
|
|
return u >= TERMINAL_KEY_UNKNOWN;
|
|
|
}
|
|
|
|
|
|
-SpecialChar convertToSpecialChar(u64 u) {
|
|
|
- SpecialChar c = {0};
|
|
|
+Core::SpecialChar Core::convertToSpecialChar(u64 u) {
|
|
|
+ SpecialChar c;
|
|
|
c.shift = TERMINAL_KEY_SHIFT & u;
|
|
|
c.control = TERMINAL_KEY_CTRL & u;
|
|
|
c.alt = TERMINAL_KEY_ALT & u;
|