Fumofumotris/source/fumoengine/terminal/term.c

204 lines
3.8 KiB
C
Raw Normal View History

2024-03-25 05:34:59 +00:00
#include <iso646.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2024-04-30 21:41:31 +00:00
#include "fumocommon.h"
2024-03-25 05:34:59 +00:00
2024-04-03 23:31:47 +00:00
struct TChar4 {
2024-03-25 05:34:59 +00:00
char ch;
u8 bg : 4;
u8 fg : 4;
};
2024-04-03 23:31:47 +00:00
struct Terminal {
2024-03-25 05:34:59 +00:00
size_t wid;
size_t hgt;
2024-04-04 19:43:45 +00:00
size_t area;
2024-04-09 07:00:48 +00:00
struct TChar4 *blks;
2024-04-04 19:43:45 +00:00
size_t buf_size;
2024-04-09 07:00:48 +00:00
char *buf;
2024-04-04 19:43:45 +00:00
2024-04-09 07:00:48 +00:00
u16f refresh_rate;
2024-03-25 05:34:59 +00:00
};
2024-04-09 07:00:48 +00:00
size_t term_buf_size(size_t area, size_t hgt)
2024-04-04 19:43:45 +00:00
{
static const size_t reset_str_len = 7;
2024-04-09 07:00:48 +00:00
static const size_t max_color_str_len = 10;
return reset_str_len + (max_color_str_len + 1) * area + hgt + 1;
}
2024-04-04 19:43:45 +00:00
2024-04-09 22:10:30 +00:00
struct TChar4 *alloc_blks(size_t area)
2024-04-09 07:00:48 +00:00
{
2024-04-09 22:10:30 +00:00
return calloc(area, sizeof(struct TChar4));
}
char *alloc_buf(size_t buf_size)
{
return malloc(buf_size);
2024-04-04 19:43:45 +00:00
}
2024-04-09 07:00:48 +00:00
bool NewTerm(struct Terminal *term, size_t wid, size_t hgt)
2024-03-25 05:34:59 +00:00
{
2024-04-04 19:43:45 +00:00
size_t area = wid * hgt;
2024-04-09 07:00:48 +00:00
size_t buf_size = term_buf_size(area, hgt);
2024-04-04 19:43:45 +00:00
2024-04-09 22:10:30 +00:00
struct TChar4 *blks = alloc_blks(area);
char *buf = alloc_buf(buf_size);
2024-04-09 07:00:48 +00:00
2024-04-09 22:10:30 +00:00
if (blks == nullptr or buf == nullptr)
2024-04-09 07:00:48 +00:00
return false;
*term = (struct Terminal) {
2024-04-03 23:31:47 +00:00
.wid = wid,
.hgt = hgt,
2024-04-04 19:43:45 +00:00
.area = area,
2024-04-09 22:10:30 +00:00
.blks = blks,
2024-03-25 05:34:59 +00:00
2024-04-09 07:00:48 +00:00
.buf_size = buf_size,
.buf = buf,
.refresh_rate = 60,
};
return true;
2024-04-04 19:43:45 +00:00
}
2024-03-25 05:34:59 +00:00
2024-04-09 07:00:48 +00:00
bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt)
2024-04-04 19:43:45 +00:00
{
size_t area = wid * hgt;
size_t buf_size = term_buf_size(area, hgt);
2024-04-09 22:10:30 +00:00
struct TChar4 *tchs = realloc(term->blks, area * sizeof(struct TChar4));
2024-04-09 07:00:48 +00:00
char *buf = realloc(term->buf, buf_size);
2024-04-09 22:10:30 +00:00
2024-04-09 07:00:48 +00:00
if (tchs == nullptr or buf == nullptr)
return false;
2024-04-04 19:43:45 +00:00
2024-04-09 07:00:48 +00:00
term->blks = tchs;
term->buf = buf;
return true;
2024-03-25 05:34:59 +00:00
}
2024-04-09 07:00:48 +00:00
void FreeTerm(struct Terminal *term)
2024-03-25 05:34:59 +00:00
{
2024-04-09 07:00:48 +00:00
free(term->blks);
free(term->buf);
2024-03-25 05:34:59 +00:00
}
2024-04-05 22:06:19 +00:00
size_t u8_to_buf(char *buf, u8f x)
{
2024-04-09 07:00:48 +00:00
size_t len = 1;
2024-04-05 22:06:19 +00:00
2024-04-09 07:00:48 +00:00
if (x > 9) {
u8f o, t;
2024-04-05 22:06:19 +00:00
2024-04-09 07:00:48 +00:00
o = x % 10;
t = x / 10;
if (x > 99) {
u8f h;
t %= 10;
h = t / 10;
len = 3;
buf[0] = h + 48;
buf[1] = t + 48;
buf[2] = o + 48;
} else {
len = 2;
buf[0] = t + 48;
buf[1] = o + 48;
}
} else {
buf[0] = x + 48;
}
return len;
2024-04-05 22:06:19 +00:00
}
2024-04-09 07:00:48 +00:00
size_t tch4_dif_to_buf(char *buf, struct TChar4 *dif, struct TChar4 *blk)
2024-04-05 22:06:19 +00:00
{
2024-04-09 07:00:48 +00:00
size_t len = 0;
if (dif->bg != blk->bg) {
dif->bg = blk->bg;
u8f bg = blk->bg + (blk->bg < 8 ? 40 : 92);
2024-04-05 22:06:19 +00:00
2024-04-09 07:00:48 +00:00
buf[len++] = '\x1b';
buf[len++] = '[';
len += u8_to_buf(buf + len, bg);
2024-04-05 22:06:19 +00:00
2024-04-09 07:00:48 +00:00
if (dif->fg != blk->fg) {
dif->fg = blk->fg;
u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82);
buf[len++] = ';';
len += u8_to_buf(buf + len, fg);
}
buf[len++] = 'm';
} else if (dif->fg != blk->fg) {
dif->fg = blk->fg;
u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82);
buf[len++] = '\x1b';
buf[len++] = '[';
len += u8_to_buf(buf + len, fg);
buf[len++] = 'm';
}
buf[len++] = blk->ch;
return len;
2024-04-05 22:06:19 +00:00
}
2024-04-09 07:00:48 +00:00
size_t TermOut(struct Terminal *term)
2024-03-25 05:34:59 +00:00
{
2024-04-09 07:00:48 +00:00
struct TChar4 dif;
2024-03-25 05:34:59 +00:00
2024-04-09 07:00:48 +00:00
size_t len = 7;
memcpy(term->buf, "\x1b[H\x1b[0m", 7);
2024-03-25 05:34:59 +00:00
2024-04-09 07:00:48 +00:00
for (size_t y = 0; y < term->hgt; y++) {
for (size_t x = 0; x < term->wid; x++) {
2024-03-25 05:34:59 +00:00
size_t i = y * term->wid + x;
2024-04-09 07:00:48 +00:00
struct TChar4 *blk = &term->blks[i];
2024-03-25 05:34:59 +00:00
// DEBUG
if (blk->ch == 0)
blk->ch = '#';
// DEBUG
2024-04-09 07:00:48 +00:00
len += tch4_dif_to_buf(term->buf + len, &dif, blk);
2024-03-25 05:34:59 +00:00
}
2024-04-09 07:00:48 +00:00
term->buf[len++] = '\n';
2024-03-25 05:34:59 +00:00
}
2024-04-09 07:00:48 +00:00
term->buf[len] = 0;
return len;
}
/*int main()
{
struct Terminal term;
NewTerm(&term, 20, 20);
for (int i = 0; i < 20 * 20; i++) {
term.blks[i].ch = 'l';
term.blks[i].bg = 0;
term.blks[i].fg = 8;
}
size_t len = TermOut(&term);
puts(term.buf);
printf("hi");
return 0;
}*/