|
@@ -0,0 +1,129 @@
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+
|
|
|
|
|
+import Core.Terminal;
|
|
|
|
|
+import Core.TerminalConstants;
|
|
|
|
|
+import Core.List;
|
|
|
|
|
+import Core.Math;
|
|
|
|
|
+import Core.ToString;
|
|
|
|
|
+import Core.Logger;
|
|
|
|
|
+
|
|
|
|
|
+using SizeVector = Core::Vector<2, size_t>;
|
|
|
|
|
+
|
|
|
|
|
+struct Cell {
|
|
|
|
|
+ Core::String<16> content{};
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static bool running = true;
|
|
|
|
|
+static SizeVector size = {20, 10};
|
|
|
|
|
+static Core::List<Cell> cells;
|
|
|
|
|
+static SizeVector cursorPosition{0, 0};
|
|
|
|
|
+
|
|
|
|
|
+static void init() {
|
|
|
|
|
+ cells.resize(size[0] * size[1]);
|
|
|
|
|
+ for(Cell& c : cells) {
|
|
|
|
|
+ c.content.format(" ");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static Cell& getCell(size_t x, size_t y) {
|
|
|
|
|
+ return cells[y * size[0] + x];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static Cell& getCell(const SizeVector& v) {
|
|
|
|
|
+ return getCell(v[0], v[1]);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void print(const char* s) {
|
|
|
|
|
+ fputs(s, stdout);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static size_t getColumnWidth(size_t x) {
|
|
|
|
|
+ size_t w = 0;
|
|
|
|
|
+ for(size_t y = 0; y < size[1]; y++) {
|
|
|
|
|
+ Cell& c = getCell(x, y);
|
|
|
|
|
+ w = Core::max(w, strlen(c.content));
|
|
|
|
|
+ }
|
|
|
|
|
+ return w;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void render() {
|
|
|
|
|
+ static constexpr const char* lc[2] = {
|
|
|
|
|
+ Core::Terminal::BG_WHITE, Core::Terminal::BG_BRIGHT_WHITE};
|
|
|
|
|
+ Core::clearTerminal();
|
|
|
|
|
+ Core::resetCursor();
|
|
|
|
|
+ Core::List<size_t> columnWidths;
|
|
|
|
|
+ for(size_t x = 0; x < size[0]; x++) {
|
|
|
|
|
+ columnWidths.add(getColumnWidth(x));
|
|
|
|
|
+ }
|
|
|
|
|
+ for(size_t y = 0; y < size[1]; y++) {
|
|
|
|
|
+ print(lc[y & 1]);
|
|
|
|
|
+ print("|");
|
|
|
|
|
+ for(size_t x = 0; x < size[0]; x++) {
|
|
|
|
|
+ Cell& c = getCell(x, y);
|
|
|
|
|
+ if(cursorPosition[0] == x && cursorPosition[1] == y) {
|
|
|
|
|
+ fputs(Core::Terminal::BG_BRIGHT_BLUE, stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ c.content.print();
|
|
|
|
|
+ size_t filler = columnWidths[x] - strlen(c.content);
|
|
|
|
|
+ while(filler > 0) {
|
|
|
|
|
+ filler--;
|
|
|
|
|
+ putchar(' ');
|
|
|
|
|
+ }
|
|
|
|
|
+ if(cursorPosition[0] == x && cursorPosition[1] == y) {
|
|
|
|
|
+ fputs(lc[y & 1], stdout);
|
|
|
|
|
+ }
|
|
|
|
|
+ print("|");
|
|
|
|
|
+ }
|
|
|
|
|
+ putchar('\n');
|
|
|
|
|
+ }
|
|
|
|
|
+ fputs(Core::Terminal::RESET, stdout);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void loop(u64 input) {
|
|
|
|
|
+ // Core::IntVector2 size = Core::getTerminalSize();
|
|
|
|
|
+ if(input == 'q') {
|
|
|
|
|
+ running = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ } else if(input == Core::Terminal::KEY_ARROW_LEFT) {
|
|
|
|
|
+ if(cursorPosition[0] > 0) {
|
|
|
|
|
+ cursorPosition += SizeVector{-1, 0};
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if(input == Core::Terminal::KEY_ARROW_RIGHT) {
|
|
|
|
|
+ if(cursorPosition[0] < size[0] - 1) {
|
|
|
|
|
+ cursorPosition += SizeVector{1, 0};
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if(input == Core::Terminal::KEY_ARROW_UP) {
|
|
|
|
|
+ if(cursorPosition[1] > 0) {
|
|
|
|
|
+ cursorPosition += SizeVector{0, -1};
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if(input == Core::Terminal::KEY_ARROW_DOWN) {
|
|
|
|
|
+ if(cursorPosition[1] < size[1] - 1) {
|
|
|
|
|
+ cursorPosition += SizeVector{0, 1};
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Cell& c = getCell(cursorPosition);
|
|
|
|
|
+ c.content.add(static_cast<char>(input));
|
|
|
|
|
+ }
|
|
|
|
|
+ render();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int main() {
|
|
|
|
|
+ Core::enterAlternativeTerminal();
|
|
|
|
|
+ if(Core::enterRawTerminal()) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ init();
|
|
|
|
|
+ render();
|
|
|
|
|
+ while(running) {
|
|
|
|
|
+ u64 u = Core::getRawChar();
|
|
|
|
|
+ if(u != 0) {
|
|
|
|
|
+ loop(u);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(Core::leaveRawTerminal()) {
|
|
|
|
|
+ puts("Could not reset terminal.");
|
|
|
|
|
+ }
|
|
|
|
|
+ Core::leaveAlternativeTerminal();
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|