#include "terminal.h" #define RESET_STR_SIZE 7 #define COLOR4_MAX_SIZE 10 usize max_out(usize wid, usize hgt) { return RESET_STR_SIZE + wid * hgt * COLOR4_MAX_SIZE + wid * hgt * UTF8_MAX_SIZE + hgt + 1; } void CreateTerminal(Alloc *pool, struct Terminal *term, usize wid, usize hgt) { term->col4s = pool->alloc(wid * hgt, sizeof(struct Color4)); term->utf8s = pool->alloc(wid * hgt, UTF8_MAX_SIZE); term->out = pool->alloc(wid * hgt, max_out(wid, hgt)); if (pool->oom) return; term->wid = wid; term->hgt = hgt; } usize u8_to_str(char *out, u8 x) { u8 ones = x % 10; u8 tens = x / 10; u8 hnds = tens / 10; tens %= 10; usize len = 0; out[len] = hnds + 48; len += (hnds != 0); out[len] = tens + 48; len += (hnds | tens) != 0; out[len++] = ones + 48; return len; } u8 ansi_bg(u8 bg) { return bg + (bg < 8 ? 40 : 92); } u8 ansi_fg(u8 fg) { return fg + (fg < 8 ? 30 : 82); } usize col4_dif_to_str(char *out, struct Color4 *dif, struct Color4 *col) { if (*(u8 *)dif == *(u8 *)col) return 0; usize len = 0; out[len++] = '\x1b'; out[len++] = '['; if (dif->bg != col->bg) { len += u8_to_str(out + len, ansi_bg(col->bg)); if (dif->fg != col->fg) { out[len++] += ';'; len += u8_to_str(out + len, ansi_fg(col->fg)); } } else if (dif->fg != col->fg) { len += u8_to_str(out + len, ansi_fg(col->fg)); } out[len++] = 'm'; *dif = *col; return len; } usize utf8_to_str(char *out, char utf8[4]) { if (utf8[0] == 0) utf8[0] = '#'; out = utf8; return 1 + (utf8[1] != 0) + (utf8[2] != 0) + (utf8[3] != 0); } usize TerminalPrint(struct Terminal *term) { term->out = (char[3]) { '\x1b', '[', 'H' }; usize len = 3; struct Color4 dif = {0}; char (*utf8)[4] = term->utf8s; struct Color4 *col4 = term->col4s; for (usize y = 0; y < term->hgt; y++) { for (usize x = 0; x < term->wid; x++, utf8++, col4++) { len += col4_dif_to_str(term->out + len, &dif, col4); len += utf8_to_str(term->out + len, *utf8); } term->out[len++] = '\n'; } *(term->out + len) = (char[4]) { '\x1b', '[', '0', 'm' }; len += 4; term->out[len] = '\0'; return len; }