summaryrefslogtreecommitdiff
path: root/src/user/libterm
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/libterm')
-rw-r--r--src/user/libterm/readline.c106
-rw-r--r--src/user/libterm/terminal.c179
-rw-r--r--src/user/libterm/termtask.c9
3 files changed, 294 insertions, 0 deletions
diff --git a/src/user/libterm/readline.c b/src/user/libterm/readline.c
new file mode 100644
index 0000000..b37801d
--- /dev/null
+++ b/src/user/libterm/readline.c
@@ -0,0 +1,106 @@
+#include <libterm/terminal.h>
+
+#include <knob/block.h>
+#include <knob/key.h>
+
+#include <stdint.h>
+
+//returns length of string without null terminator
+//max_length doesn't include null terminator
+uint32_t read_line(char *sz, uint32_t max_length, const char *prompt) {
+ term_add_sz(prompt);
+ term_add_char(' ');
+ term_paint();
+
+ uint32_t l = 0;
+ uint32_t c = 0;
+
+ while (1) {
+ struct key_packet kp = term_get_key_blocking();
+ switch (kp.key_id) {
+ case KEY_LEFT_ARROW:
+ if (c) {
+ --c;
+ term_cursor_left();
+ term_paint();
+ }
+ continue;
+ case KEY_RIGHT_ARROW:
+ if (c != l) {
+ ++c;
+ term_cursor_right();
+ term_paint();
+ }
+ continue;
+ case KEY_HOME:
+ while (c) {
+ --c;
+ term_cursor_left();
+ }
+ term_paint();
+ continue;
+ case KEY_END:
+ while (c != l) {
+ ++c;
+ term_cursor_right();
+ }
+ term_paint();
+ continue;
+ case KEY_DELETE:
+ if (c != l) {
+ ++c;
+ term_cursor_right();
+ }
+ case KEY_BSPACE:
+ if (!c)
+ continue;
+ --c;
+ --l;
+ for (uint32_t i = c; i < l; ++i)
+ sz[i] = sz[i + 1];
+ term_cursor_left();
+ term_add_sn_no_ww(sz + c, l - c);
+ term_add_char(' ');
+ for (uint32_t i = l + 1; i > c; --i)
+ term_cursor_left();
+ term_paint();
+ continue;
+ case KEY_ENTER:
+ while (c != l) {
+ ++c;
+ term_cursor_right();
+ }
+ sz[l] = '\0';
+ term_add_char('\n');
+ term_paint();
+ return l;
+ default:
+ if (l == max_length)
+ continue;
+ char ch = key_to_char(kp);
+ if (!ch)
+ continue;
+ if (c == l) {
+ ++l;
+ term_add_char(sz[c++] = ch);
+ term_paint();
+ continue;
+ }
+ if (!(kp.modifiers & INSERT)) {
+ term_add_char(sz[c++] = ch);
+ term_paint();
+ continue;
+ }
+ for (uint32_t i = l; i > c; --i)
+ sz[i] = sz[i - 1];
+ sz[c] = ch;
+ ++l;
+ term_add_sn_no_ww(sz + c, l - c);
+ ++c;
+ for (uint32_t i = l; i > c; --i)
+ term_cursor_left();
+ term_paint();
+ continue;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/user/libterm/terminal.c b/src/user/libterm/terminal.c
new file mode 100644
index 0000000..387d63f
--- /dev/null
+++ b/src/user/libterm/terminal.c
@@ -0,0 +1,179 @@
+#include <libterm/command.h>
+
+#include <knob/format.h>
+#include <knob/block.h>
+#include <knob/ipc.h>
+
+_task_handle_t term_task;
+
+void term_set_dimensions(uint32_t width, uint32_t height) {
+ struct terminal_command cmd = {
+ .kind = SET_DIMENSIONS,
+ .as_coords = {
+ .x = width,
+ .y = height
+ }
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_get_dimensions(uint32_t *width, uint32_t *height) {
+ struct terminal_command cmd = {
+ .kind = GET_DIMENSIONS
+ };
+
+ if (try_send_command(&cmd)) {
+ union terminal_response rs;
+ if (try_get_response(&rs)) {
+ *width = rs.as_coords.x;
+ *height = rs.as_coords.y;
+ }
+ }
+}
+
+void term_paint() {
+ struct terminal_command cmd = {
+ .kind = PAINT
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_clear() {
+ struct terminal_command cmd = {
+ .kind = CLEAR
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_set_color(uint8_t fg, uint8_t bg) {
+ struct terminal_command cmd = {
+ .kind = SET_COLOR,
+ .as_color = {
+ .fg = fg,
+ .bg = bg
+ }
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_set_cursor(uint32_t new_y, uint32_t new_x) {
+ struct terminal_command cmd = {
+ .kind = SET_CURSOR,
+ .as_coords = {
+ .y = new_y,
+ .x = new_x
+ }
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_cursor_left() {
+ struct terminal_command cmd = {
+ .kind = CURSOR_LEFT
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_cursor_right() {
+ struct terminal_command cmd = {
+ .kind = CURSOR_RIGHT
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_cursor_up() {
+ struct terminal_command cmd = {
+ .kind = CURSOR_UP
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_cursor_down() {
+ struct terminal_command cmd = {
+ .kind = CURSOR_DOWN
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_add_char(char ch) {
+ struct terminal_command cmd = {
+ .kind = ADD_CHAR,
+ .as_char = ch
+ };
+
+ try_send_command(&cmd);
+}
+
+void term_add_sn_no_ww(const char *s, uint32_t n) {
+ struct terminal_command cmd = {
+ .kind = ADD_SN_NO_WORDWRAP,
+ .as_uint = n
+ };
+
+ if (try_send_command(&cmd))
+ try_send_ipc(term_task, s, n);
+}
+
+void term_add_sz_no_ww(const char *sz) {
+ term_add_sn_no_ww(sz, strlen(sz));
+}
+
+void term_add_sz(const char *sz) {
+ const uint32_t len = strlen(sz);
+
+ struct terminal_command cmd = {
+ .kind = ADD_SN,
+ .as_uint = len
+ };
+
+ if (try_send_command(&cmd))
+ try_send_ipc(term_task, sz, len);
+}
+
+void term_addf_no_ww_v(const char *fmt, va_list args) {
+ char *const msg = format_v(fmt, args);
+ term_add_sz_no_ww(msg);
+ free_block(msg);
+}
+
+void term_addf_no_ww(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ term_addf_no_ww_v(fmt, args);
+ va_end(args);
+}
+
+void term_addf_v(const char *fmt, va_list args) {
+ char *const msg = format_v(fmt, args);
+ term_add_sz(msg);
+ free_block(msg);
+}
+
+void term_addf(const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ term_addf_v(fmt, args);
+ va_end(args);
+}
+
+struct key_packet term_get_key_blocking() {
+ struct terminal_command cmd = {
+ .kind = GET_KEY
+ };
+
+ try_send_command(&cmd);
+
+ union terminal_response rs;
+ try_get_response(&rs);
+
+ return rs.as_key;
+}
diff --git a/src/user/libterm/termtask.c b/src/user/libterm/termtask.c
new file mode 100644
index 0000000..cc853a6
--- /dev/null
+++ b/src/user/libterm/termtask.c
@@ -0,0 +1,9 @@
+#include <libterm/command.h>
+
+#include <pland/pcrt.h>
+
+void set_term_task_to_stdio() {
+ term_task = stdio_task;
+}
+
+BEFORE_MAIN(set_term_task_to_stdio); \ No newline at end of file