Fumofumotris/rewrite/c/terminal.c
2024-05-24 00:36:13 -05:00

118 lines
2.1 KiB
C

#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;
}