diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-17 00:51:46 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-17 00:51:46 -0400 |
commit | f3e6838b44a5b37ce7664db5b8662e3d02e5f539 (patch) | |
tree | e97eeeabab78ba2c84d3b0069c8db9911cd021b2 /kernel/term.c | |
parent | fmt (diff) | |
download | comus-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.c | 169 |
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(); +} |