summaryrefslogtreecommitdiff
path: root/kernel/term.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-17 00:51:46 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-17 00:51:46 -0400
commitf3e6838b44a5b37ce7664db5b8662e3d02e5f539 (patch)
treee97eeeabab78ba2c84d3b0069c8db9911cd021b2 /kernel/term.c
parentfmt (diff)
downloadcomus-f3e6838b44a5b37ce7664db5b8662e3d02e5f539.tar.gz
comus-f3e6838b44a5b37ce7664db5b8662e3d02e5f539.tar.bz2
comus-f3e6838b44a5b37ce7664db5b8662e3d02e5f539.zip
font rending in framebuffer yay!!
Diffstat (limited to 'kernel/term.c')
-rw-r--r--kernel/term.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/kernel/term.c b/kernel/term.c
new file mode 100644
index 0000000..e40e0fe
--- /dev/null
+++ b/kernel/term.c
@@ -0,0 +1,169 @@
+#include "lib/kio.h"
+#include <lib.h>
+#include <comus/term.h>
+#include <comus/asm.h>
+#include <comus/limits.h>
+#include <comus/memory.h>
+#include <comus/drivers/vga.h>
+#include <comus/drivers/uart.h>
+
+// draw function
+static void (*draw_char)(char c, uint16_t x, uint16_t y) = vga_draw_char;
+
+// terminal data
+static char buffer[TERM_MAX_WIDTH * TERM_MAX_HEIGHT];
+static uint16_t buffer_line = UINT16_MAX;
+static uint16_t width = VGA_WIDTH;
+static uint16_t height = VGA_HEIGHT;
+static uint16_t x = 0;
+static uint16_t y = 0;
+
+#define BUFY(y) ((buffer_line + (y)) % TERM_MAX_HEIGHT)
+#define BUFIDX(x,y) ((x) + (BUFY(y) * TERM_MAX_WIDTH))
+
+static void buffer_check(void)
+{
+ if (buffer_line == UINT16_MAX) {
+ buffer_line = 0;
+ memset(buffer, 0, sizeof(buffer));
+ }
+}
+
+static inline bool printable(char c)
+{
+ switch (c) {
+ case '\0':
+ case '\n':
+ case '\t':
+ case '\v':
+ case '\f':
+ case '\r':
+ return false;
+ default:
+ return true;
+ }
+}
+
+static inline void term_move_cur(char c)
+{
+ if (c == '\0')
+ return;
+
+ switch (c) {
+ case '\n':
+ x = 0;
+ y++;
+ break;
+ case '\t':
+ x += 4;
+ break;
+ case '\v':
+ case '\f':
+ y++;
+ break;
+ case '\r':
+ x = 0;
+ break;
+ default:
+ x++;
+ }
+
+ if (x >= width) {
+ x = 0;
+ y++;
+ }
+ if (y >= height) {
+ term_scroll(y - (height - 1));
+ y = height - 1;
+ }
+}
+
+uint16_t term_width(void)
+{
+ return width;
+}
+
+uint16_t term_height(void)
+{
+ return height;
+}
+
+void term_out(char c)
+{
+ term_out_at(c, x, y);
+ term_move_cur(c);
+}
+
+void term_out_at(char c, uint16_t x, uint16_t y)
+{
+ buffer_check();
+
+ if (!printable(c))
+ return;
+
+ buffer[BUFIDX(x, y)] = c;
+ draw_char(c, x, y);
+}
+
+void term_out_str(const char *str)
+{
+ char c;
+ while (c = *(str++), c) {
+ term_out_at(c, x, y);
+ term_move_cur(c);
+ }
+}
+
+void term_out_str_at(const char *str, uint16_t x, uint16_t y)
+{
+ char c;
+ while (c = *(str++), c)
+ term_out_at(c, x, y);
+}
+
+void term_clear(void)
+{
+ for (uint16_t y = 0; y < height; y++)
+ term_clear_line(y);
+}
+
+void term_clear_line(uint16_t line)
+{
+ buffer_check();
+
+ if (line > height)
+ return;
+
+ for (uint16_t x = 0; x < width; x++) {
+ buffer[BUFIDX(x, line)] = 0;
+ draw_char(0, x, line);
+ }
+}
+
+void term_redraw(void)
+{
+ buffer_check();
+
+ for (uint16_t j = 0; j < height; j++) {
+ for (uint16_t i = 0; i < width; i++) {
+ char c = buffer[BUFIDX(i, j)];
+ draw_char(c, i, j);
+ }
+ }
+}
+
+void term_scroll(uint16_t lines)
+{
+ if (!lines)
+ return;
+ buffer_line += lines;
+ term_redraw();
+}
+
+void term_switch_handler(uint16_t w, uint16_t h, void (*fn)(char c, uint16_t x, uint16_t y))
+{
+ draw_char = fn;
+ width = w % TERM_MAX_WIDTH;
+ height = h % TERM_MAX_HEIGHT;
+ term_redraw();
+}