#include #include #include #include #include "framebuffer.h" size_t term_width = 0, term_height = 0; struct termios initial_terminal_state = {0}; Framebuffer fb_new(size_t width, size_t height) { Framebuffer fb; /* In case malloc() fails and we return early */ fb.width = 0; fb.height = 0; fb.fb = malloc(sizeof(Pixel *) * height); if (fb.fb == NULL) return fb; for (size_t i = 0; i < height; i++) { fb.fb[i] = malloc(sizeof(Pixel) * width); if (fb.fb[i] == NULL) { /* FIXME: Memory leak; should free all prev. malloced rows */ fb.fb = NULL; return fb; } } fb.width = width; fb.height = height; return fb; } void fb_free(Framebuffer *fb) { if (fb->fb == NULL) goto ret; for (size_t i = 0; i < fb->height; i++) { free(fb->fb[i]); } free(fb->fb); ret: fb->width = 0; fb->height = 0; return; } void fb_fill(Framebuffer fb, Pixel pixel) { for (size_t row = 0; row < fb.height; row++) { for (size_t col = 0; col < fb.width; col++) { fb_put(fb, row, col, pixel); } } } void inline fb_put(Framebuffer fb, size_t row, size_t col, Pixel pixel) { fb.fb[row][col] = pixel; } void term_init(void) { tcgetattr(0, &initial_terminal_state); struct termios new = initial_terminal_state; new.c_lflag &= ~ICANON; /* Turn off canonical mode */ new.c_lflag &= ~ECHO; /* Turn off echoing */ new.c_cc[VMIN] = 1; /* One char at a time */ new.c_cc[VTIME] = 0; /* No input timeout */ tcsetattr(0, TCSANOW, &new); write(STDOUT_FILENO, "\x1b[?1049h", 8); /* Alternative screen buffer */ write(STDOUT_FILENO, "\x1b[H", 3); /* Move cursor to top-left */ write(STDOUT_FILENO, "\x1b[?25l", 6); /* Hide the cursor */ term_update_size(); } void term_cleanup(void) { tcsetattr(0, TCSANOW, &initial_terminal_state); write(STDOUT_FILENO, "\x1b[?25h", 6); /* Show the cursor */ write(STDOUT_FILENO, "\x1b[?1049l", 8); /* Alternative screen buffer */ } void term_update_size(void) { #if defined(TIOCGWINSZ) struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) { term_height = ws.ws_row; term_width = ws.ws_col; return; } #elif defined(TIOCGSIZE) struct ttysize ts; if (ioctl(STDOUT_FILENO, TIOCGSIZE, &ts) == 0) { term_height = ts.ts_row; term_width = ts.ts_col; return; } #else #error "Neither TIOCGWINSZ or TIOCGSIZE are defined, can't proceed" #endif } void fb_print(Framebuffer fb) { write(STDOUT_FILENO, "\x1b[H", 3); /* Move cursor to top-left */ /* TODO: finish me */ }