HhhOS/arch/i386/drivers/terminal/terminal.c

147 lines
3.4 KiB
C

#include <drivers/terminal/terminal.h>
#include <drivers/device/device.h>
size_t terminal_row;
size_t terminal_column;
uint8_t terminal_color;
uint16_t *terminal_buffer;
framebuffer_t *terminal_framebuffer;
void terminal_clear() {
for (size_t y = 0; y < VGA_HEIGHT; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_entry(' ', terminal_color);
}
}
}
/*
static inline void terminal_writestring(const char* data) {
terminal_write(data, strlen(data));
}
static inline void terminal_writeline(const char* data) {
terminal_writestring(data);
terminal_putchar('\n');
}
*/
void* terminal_devread(void* data) {
return NULL;
}
void* terminal_devwrite(void* data) {
terminal_putchar(*((char*)data));
return NULL;
}
int terminal_initialize(framebuffer_t *terminal_fb) {
terminal_framebuffer = terminal_fb;
terminal_row = 0;
terminal_column = 0;
terminal_color = vga_entry_color(VGA_COLOR_BLACK, VGA_COLOR_WHITE);
terminal_buffer = (uint16_t*) 0xB8000;
terminal_clear();
struct device terminal_device = {
write: &terminal_devwrite,
read: &terminal_devread
};
return push_device(terminal_device);
}
void terminal_setcolor(uint8_t color) {
terminal_color = color;
}
void terminal_clearline(size_t line) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = line * VGA_WIDTH + x;
terminal_buffer[index] = vga_entry(' ', terminal_color);
}
}
void terminal_clearlines(size_t from, size_t to) {
for (size_t y = from; y <= to; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_entry(' ', terminal_color);
}
}
}
void terminal_updatecursor() {
size_t temp = terminal_row * VGA_WIDTH + terminal_column;
outportb(0x3D4, 14);
outportb(0x3D5, temp >> 8);
outportb(0x3D4, 15);
outportb(0x3D5, temp);
}
void terminal_scrollup() {
for (size_t index = 0; index < VGA_WIDTH * (VGA_HEIGHT - 1); index++) {
terminal_buffer[index] = terminal_buffer[index + VGA_WIDTH];
}
terminal_clearline(VGA_HEIGHT);
if ((terminal_row - 1) < 0) {
terminal_row = 0;
terminal_column = 0;
} else {
terminal_row -= 1;
}
terminal_updatecursor();
}
void terminal_checknewline() {
if (terminal_row >= VGA_HEIGHT - 1) {
terminal_scrollup();
}
}
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
//terminal_buffer[y * VGA_WIDTH + x] = vga_entry(c, color);
draw_psf_char(terminal_framebuffer, c, x, y, 0xFFFFFFFF, 0);
}
void terminal_putchar(char c) {
outportb(0x3F8, c); // log terminal to serial.log when running on qemu
switch (c) {
case '\b':
if (--terminal_column < 0) {
if (terminal_row-- > 0) {
terminal_column = VGA_WIDTH - 1;
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
}
} else {
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
}
terminal_updatecursor();
return;
case '\r':
terminal_column = 0;
break;
case '\n':
terminal_column = 0;
terminal_row++;
break;
default:
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
terminal_column++;
}
if (terminal_column >= VGA_WIDTH) {
terminal_column = 0;
terminal_row++;
}
terminal_updatecursor();
terminal_checknewline();
}
void terminal_write(const char* data, size_t size) {
for (size_t i = 0; i < size; i++)
terminal_putchar(data[i]);
}