X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/e0ee3d449aacd33a84cb1f58961e55f9f06acb46..2803826a2373620dbfce8a5bff1e6a01dd594953:/lunaix-os/kernel/tty/tty.c diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index cb4f1b4..4164239 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -1,58 +1,156 @@ +#include +#include +#include #include #include #define TTY_WIDTH 80 #define TTY_HEIGHT 25 -vga_atrributes *buffer = 0xB8000; +static vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; -vga_atrributes theme_color = VGA_COLOR_BLACK; +static vga_attribute tty_theme_color = VGA_COLOR_BLACK; -uint32_t TTY_COLUMN = 0; -uint16_t TTY_ROW = 0; +static uint32_t tty_x = 0; +static uint32_t tty_y = 0; -void tty_set_theme(vga_atrributes fg, vga_atrributes bg) { - theme_color = (bg << 4 | fg) << 8; +void +tty_init(void* vga_buf) +{ + tty_vga_buffer = (vga_attribute*)vga_buf; + tty_clear(); + + io_outb(0x3D4, 0x0A); + io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); + + io_outb(0x3D4, 0x0B); + io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15); +} + +void +tty_set_buffer(void* vga_buf) +{ + tty_vga_buffer = (vga_attribute*)vga_buf; +} + +void +tty_set_theme(vga_attribute fg, vga_attribute bg) +{ + tty_theme_color = (bg << 4 | fg) << 8; } -void tty_put_char(char chr) { - if (chr == '\n') { - TTY_COLUMN = 0; - TTY_ROW++; +void +tty_put_char(char chr) +{ + switch (chr) { + case '\t': + tty_x += 4; + break; + case '\n': + tty_y++; + // fall through + case '\r': + tty_x = 0; + break; + case '\x08': + tty_x = tty_x ? tty_x - 1 : 0; + *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = + (tty_theme_color | 0x20); + break; + default: + *(tty_vga_buffer + tty_x + tty_y * TTY_WIDTH) = + (tty_theme_color | chr); + tty_x++; + break; } - else if (chr == '\r') { - TTY_COLUMN = 0; + + if (tty_x >= TTY_WIDTH) { + tty_x = 0; + tty_y++; } - else { - *(buffer + TTY_COLUMN + TTY_ROW * TTY_WIDTH) = (theme_color | chr); - TTY_COLUMN++; - if (TTY_COLUMN >= TTY_WIDTH) { - TTY_COLUMN = 0; - TTY_ROW++; - } + if (tty_y >= TTY_HEIGHT) { + tty_scroll_up(); } +} - if (TTY_ROW >= TTY_HEIGHT) { - tty_scroll_up(); - TTY_ROW--; - } +void +tty_sync_cursor() +{ + tty_set_cursor(tty_x, tty_y); } -void tty_put_str(char* str) { +void +tty_set_cursor(uint8_t x, uint8_t y) +{ + if (x >= TTY_WIDTH || y >= TTY_HEIGHT) { + x = y = 0; + } + uint32_t pos = y * TTY_WIDTH + x; + io_outb(0x3D4, 14); + io_outb(0x3D5, pos / 256); + io_outb(0x3D4, 15); + io_outb(0x3D5, pos % 256); +} + +void +tty_put_str(char* str) +{ while (*str != '\0') { tty_put_char(*str); str++; } + // FIXME: This does not work in user mode. + // Work around: + // 1. (Easy) Define an IO Permission bitmap in TSS + // 2. (More effort) Mount onto file system. (/dev/tty) + // tty_sync_cursor(); +} + +void +tty_scroll_up() +{ + size_t last_line = TTY_WIDTH * (TTY_HEIGHT - 1); + memcpy(tty_vga_buffer, tty_vga_buffer + TTY_WIDTH, last_line * 2); + for (size_t i = 0; i < TTY_WIDTH; i++) { + *(tty_vga_buffer + i + last_line) = tty_theme_color; + } + tty_y = tty_y == 0 ? 0 : TTY_HEIGHT - 1; } -void tty_scroll_up() { - // TODO use memcpy +void +tty_clear() +{ + for (uint32_t i = 0; i < TTY_WIDTH * TTY_HEIGHT; i++) { + *(tty_vga_buffer + i) = tty_theme_color; + } + tty_x = 0; + tty_y = 0; } -void tty_clear() { - for (uint32_t x = 0; x < TTY_WIDTH; x++) { - for (uint32_t y = 0; y < TTY_HEIGHT; y++) { - *(buffer + x + y * TTY_WIDTH) = theme_color; - } +void +tty_clear_line(unsigned int y) +{ + for (size_t i = 0; i < TTY_WIDTH; i++) { + *(tty_vga_buffer + i + y * TTY_WIDTH) = tty_theme_color; } +} + +void +tty_set_cpos(unsigned int x, unsigned int y) +{ + tty_x = x % TTY_WIDTH; + tty_y = y % TTY_HEIGHT; +} + +void +tty_get_cpos(unsigned int* x, unsigned int* y) +{ + *x = tty_x; + *y = tty_y; +} + +vga_attribute +tty_get_theme() +{ + return tty_theme_color; } \ No newline at end of file