term: General terminal improvements
diff --git a/stage23/lib/term.s2.c b/stage23/lib/term.s2.c
index 0f7bfb3b..5701d2a0 100644
--- a/stage23/lib/term.s2.c
+++ b/stage23/lib/term.s2.c
@@ -7,7 +7,11 @@
#include <lib/blib.h>
#include <drivers/vga_textmode.h>
+// Tries to implement this standard for terminfo
+// https://man7.org/linux/man-pages/man4/console_codes.4.html
+
#define TERM_TABSIZE (8)
+#define MAX_ESC_VALUES (256)
int current_video_mode = -1;
@@ -74,125 +78,118 @@ static int get_cursor_pos_y(void) {
return y;
}
-static void escape_parse(uint8_t c);
+static bool control_sequence = false;
+static bool escape = false;
+static bool rrr = false;
+static int esc_values[MAX_ESC_VALUES];
+static int esc_values_i = 0;
+static int saved_cursor_x = 0, saved_cursor_y = 0;
-static int escape = 0;
-static int esc_value0 = 0;
-static int esc_value1 = 0;
-static int *esc_value = &esc_value0;
-static int esc_default0 = 1;
-static int esc_default1 = 1;
-static int *esc_default = &esc_default0;
+static void sgr(void) {
+ int i = 0;
-static void term_putchar(uint8_t c) {
- if (escape) {
- escape_parse(c);
- return;
- }
- switch (c) {
- case 0x00:
- break;
- case '\e':
- escape = 1;
- return;
- case '\t':
- if ((get_cursor_pos_x() / TERM_TABSIZE + 1) >= term_cols)
- break;
- set_cursor_pos((get_cursor_pos_x() / TERM_TABSIZE + 1) * TERM_TABSIZE, get_cursor_pos_y());
- break;
- default:
- raw_putchar(c);
- break;
- }
-}
+ if (!esc_values_i)
+ goto def;
-static void sgr(void) {
- if (esc_value0 == 0){
- set_text_bg(8);
- set_text_fg(9);
- return;
- }
+ for (; i < esc_values_i; i++) {
+ if (!esc_values[i]) {
+def:
+ set_text_bg(8);
+ set_text_fg(9);
+ continue;
+ }
- if (esc_value0 >= 30 && esc_value0 <= 37) {
- set_text_fg(esc_value0 - 30);
- return;
- }
+ if (esc_values[i] >= 30 && esc_values[i] <= 37) {
+ set_text_fg(esc_values[i] - 30);
+ continue;
+ }
- if (esc_value0 >= 40 && esc_value0 <= 47) {
- set_text_bg(esc_value0 - 40);
- return;
+ if (esc_values[i] >= 40 && esc_values[i] <= 47) {
+ set_text_bg(esc_values[i] - 40);
+ continue;
+ }
}
}
-static void escape_parse(uint8_t c) {
+static void control_sequence_parse(uint8_t c) {
if (c >= '0' && c <= '9') {
- *esc_value *= 10;
- *esc_value += c - '0';
- *esc_default = 0;
+ rrr = true;
+ esc_values[esc_values_i] *= 10;
+ esc_values[esc_values_i] += c - '0';
return;
+ } else {
+ if (rrr == true) {
+ esc_values_i++;
+ rrr = false;
+ if (c == ';')
+ return;
+ } else if (c == ';') {
+ esc_values[esc_values_i] = 1;
+ esc_values_i++;
+ return;
+ }
}
+ // default rest to 1
+ for (int i = esc_values_i; i < MAX_ESC_VALUES; i++)
+ esc_values[i] = 1;
+
switch (c) {
- case 0x1b:
- escape = 0;
- raw_putchar(0x1b);
- return;
- case '[':
- return;
- case ';':
- esc_value = &esc_value1;
- esc_default = &esc_default1;
- return;
case 'A':
- if (esc_default0)
- esc_value0 = 1;
- if (esc_value0 > get_cursor_pos_y())
- esc_value0 = get_cursor_pos_y();
- set_cursor_pos(get_cursor_pos_x(),
- get_cursor_pos_y() - esc_value0);
+ if (esc_values[0] > get_cursor_pos_y())
+ esc_values[0] = get_cursor_pos_y();
+ set_cursor_pos(get_cursor_pos_x(), get_cursor_pos_y() - esc_values[0]);
break;
case 'B':
- if (esc_default0)
- esc_value0 = 1;
- if ((get_cursor_pos_y() + esc_value0) > (term_rows - 1))
- esc_value0 = (term_rows - 1) - get_cursor_pos_y();
- set_cursor_pos(get_cursor_pos_x(),
- get_cursor_pos_y() + esc_value0);
+ if ((get_cursor_pos_y() + esc_values[0]) > (term_rows - 1))
+ esc_values[0] = (term_rows - 1) - get_cursor_pos_y();
+ set_cursor_pos(get_cursor_pos_x(), get_cursor_pos_y() + esc_values[0]);
break;
case 'C':
- if (esc_default0)
- esc_value0 = 1;
- if ((get_cursor_pos_x() + esc_value0) > (term_cols - 1))
- esc_value0 = (term_cols - 1) - get_cursor_pos_x();
- set_cursor_pos(get_cursor_pos_x() + esc_value0,
- get_cursor_pos_y());
+ if ((get_cursor_pos_x() + esc_values[0]) > (term_cols - 1))
+ esc_values[0] = (term_cols - 1) - get_cursor_pos_x();
+ set_cursor_pos(get_cursor_pos_x() + esc_values[0], get_cursor_pos_y());
break;
case 'D':
- if (esc_default0)
- esc_value0 = 1;
- if (esc_value0 > get_cursor_pos_x())
- esc_value0 = get_cursor_pos_x();
- set_cursor_pos(get_cursor_pos_x() - esc_value0,
- get_cursor_pos_y());
+ if (esc_values[0] > get_cursor_pos_x())
+ esc_values[0] = get_cursor_pos_x();
+ set_cursor_pos(get_cursor_pos_x() - esc_values[0], get_cursor_pos_y());
break;
- case 'H':
- esc_value0--;
- esc_value1--;
- if (esc_default0)
- esc_value0 = 0;
- if (esc_default1)
- esc_value1 = 0;
- if (esc_value1 >= term_cols)
- esc_value1 = term_cols - 1;
- if (esc_value0 >= term_rows)
- esc_value0 = term_rows - 1;
- set_cursor_pos(esc_value1, esc_value0);
+ case 'E':
+ if (get_cursor_pos_y() + esc_values[0] >= term_rows)
+ set_cursor_pos(0, term_rows - 1);
+ else
+ set_cursor_pos(0, get_cursor_pos_y() + esc_values[0]);
break;
- case 'm':
- sgr();
+ case 'F':
+ if (get_cursor_pos_y() - esc_values[0] < 0)
+ set_cursor_pos(0, 0);
+ else
+ set_cursor_pos(0, get_cursor_pos_y() - esc_values[0]);
+ break;
+ case 'd':
+ if (esc_values[0] >= term_rows)
+ break;
+ set_cursor_pos(get_cursor_pos_x(), esc_values[0]);
+ break;
+ case 'G':
+ case '`':
+ if (esc_values[0] >= term_cols)
+ break;
+ set_cursor_pos(esc_values[0], get_cursor_pos_y());
+ break;
+ case 'H':
+ case 'f':
+ esc_values[0] -= 1;
+ esc_values[1] -= 1;
+ if (esc_values[1] >= term_cols)
+ esc_values[1] = term_cols - 1;
+ if (esc_values[0] >= term_rows)
+ esc_values[0] = term_rows - 1;
+ set_cursor_pos(esc_values[1], esc_values[0]);
break;
case 'J':
- switch (esc_value0) {
+ switch (esc_values[0]) {
case 2:
clear(false);
break;
@@ -200,11 +197,20 @@ static void escape_parse(uint8_t c) {
break;
}
break;
+ case 'm':
+ sgr();
+ break;
+ case 's':
+ get_cursor_pos(&saved_cursor_x, &saved_cursor_y);
+ break;
+ case 'u':
+ set_cursor_pos(saved_cursor_x, saved_cursor_y);
+ break;
case 'K':
- switch (esc_value0) {
+ switch (esc_values[0]) {
case 2: {
- int x = get_cursor_pos_x();
- int y = get_cursor_pos_y();
+ int x, y;
+ get_cursor_pos(&x, &y);
set_cursor_pos(0, y);
for (int i = 0; i < term_cols; i++)
raw_putchar(' ');
@@ -212,18 +218,53 @@ static void escape_parse(uint8_t c) {
break;
}
}
+ default:
+ break;
+ }
+
+ control_sequence = false;
+ escape = false;
+}
+
+static void escape_parse(uint8_t c) {
+ if (control_sequence == true) {
+ control_sequence_parse(c);
+ return;
+ }
+
+ switch (c) {
+ case '[':
+ for (int i = 0; i < MAX_ESC_VALUES; i++)
+ esc_values[i] = 0;
+ esc_values_i = 0;
+ rrr = false;
+ control_sequence = true;
break;
default:
- escape = 0;
- raw_putchar('?');
+ escape = false;
break;
}
+}
+
+static void term_putchar(uint8_t c) {
+ if (escape == true) {
+ escape_parse(c);
+ return;
+ }
- esc_value = &esc_value0;
- esc_value0 = 0;
- esc_value1 = 0;
- esc_default = &esc_default0;
- esc_default0 = 1;
- esc_default1 = 1;
- escape = 0;
+ switch (c) {
+ case '\0':
+ break;
+ case '\e':
+ escape = 1;
+ return;
+ case '\t':
+ if ((get_cursor_pos_x() / TERM_TABSIZE + 1) >= term_cols)
+ break;
+ set_cursor_pos((get_cursor_pos_x() / TERM_TABSIZE + 1) * TERM_TABSIZE, get_cursor_pos_y());
+ break;
+ default:
+ raw_putchar(c);
+ break;
+ }
}
diff --git a/stage23/menu.c b/stage23/menu.c
index f30fc181..29716268 100644
--- a/stage23/menu.c
+++ b/stage23/menu.c
@@ -416,11 +416,12 @@ refresh:
if (skip_timeout == false) {
print("\n\n");
for (int i = timeout; i; i--) {
- print("\rBooting automatically in %u, press any key to stop the countdown...", i);
+ print("\e[2K\rBooting automatically in %u, press any key to stop the countdown...", i);
term_double_buffer_flush();
if ((c = pit_sleep_and_quit_on_keypress(1))) {
skip_timeout = true;
print("\e[2K\r\e[2A");
+ term_double_buffer_flush();
goto timeout_aborted;
}
}
