Files
bluelib/term/tty.c

351 lines
11 KiB
C
Raw Normal View History

#include "tty.h"
#include <blue/core/hash.h>
#include <blue/term/tty.h>
#include <string.h>
#define MOD_HASH_BLACK 0x4b5dd0abbc6fc1e4
#define MOD_HASH_RED 0x89e9be1960f4c21c
#define MOD_HASH_GREEN 0x0f40f029637fecbc
#define MOD_HASH_YELLOW 0x8346a574925e75a9
#define MOD_HASH_BLUE 0xc5ccd29bc2dda64d
#define MOD_HASH_MAGENTA 0x6c90e772edbc8708
#define MOD_HASH_CYAN 0x70ae2e90c1bce27a
#define MOD_HASH_WHITE 0xced973885856e206
#define MOD_HASH_DARK_GREY 0x55a19de854654d99
#define MOD_HASH_BRIGHT_RED 0xbad8e3fe841b9385
#define MOD_HASH_BRIGHT_GREEN 0x11cc5e579bdd2fb9
#define MOD_HASH_BRIGHT_YELLOW 0xfd579007fe8579f6
#define MOD_HASH_BRIGHT_BLUE 0x57c76bf18badb6d6
#define MOD_HASH_BRIGHT_MAGENTA 0xf6ecc6d3fdfec129
#define MOD_HASH_BRIGHT_CYAN 0x03df73fd4e12ec6d
#define MOD_HASH_BRIGHT_WHITE 0xb5ebc3323f57d7fb
#define MOD_HASH_BG_BLACK 0xd87a8f2d9d394432
#define MOD_HASH_BG_RED 0x145b1e4366c7d7aa
#define MOD_HASH_BG_GREEN 0xa00b8541d3b1e55a
#define MOD_HASH_BG_YELLOW 0x98b030fd86e3b3cf
#define MOD_HASH_BG_BLUE 0xa15529109506b5df
#define MOD_HASH_BG_MAGENTA 0x86dbda99bcc86222
#define MOD_HASH_BG_CYAN 0xf16a3104cf61a098
#define MOD_HASH_BG_WHITE 0x3408c46ab5836674
#define MOD_HASH_BG_DARK_GREY 0x820d2e77568eec47
#define MOD_HASH_BRIGHT_BG_RED 0x144f5dc138087701
#define MOD_HASH_BRIGHT_BG_GREEN 0xc4d88c6426ffe355
#define MOD_HASH_BRIGHT_BG_YELLOW 0xf7bb000a4a792602
#define MOD_HASH_BRIGHT_BG_BLUE 0x9b5c16d6807a1002
#define MOD_HASH_BRIGHT_BG_MAGENTA 0xc59fb2196cdba3fd
#define MOD_HASH_BRIGHT_BG_CYAN 0x46feb6dc999a6f09
#define MOD_HASH_BRIGHT_BG_WHITE 0xa3e7d1da08826f5f
#define MOD_HASH_BOLD 0xcd32ea9bc6b26ff6
#define MOD_HASH_ULINE 0x141fe741e9f8c22a
#define MOD_HASH_ITALIC 0x69d5e5f057d8992d
#define MOD_HASH_INVERT 0xab4ab85ddd6232e1
#define MOD_HASH_RESET 0x0f136ff2c086b760
#define COMPARE_MOD_NAME(ss, sd, hs, hd) ((hs) == (hd) && !strcmp(ss, sd))
static void apply_code_to_vmode(struct tty_format_buf *fmt)
{
const char *modifier = fmt->buf;
2025-09-22 10:55:04 +01:00
uint64_t mod_hash = b_hash_cstr(modifier);
if (COMPARE_MOD_NAME(modifier, "black", mod_hash, MOD_HASH_BLACK)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BLACK;
}
if (COMPARE_MOD_NAME(modifier, "red", mod_hash, MOD_HASH_RED)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_RED;
}
if (COMPARE_MOD_NAME(modifier, "green", mod_hash, MOD_HASH_GREEN)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_GREEN;
}
if (COMPARE_MOD_NAME(modifier, "yellow", mod_hash, MOD_HASH_YELLOW)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_YELLOW;
}
if (COMPARE_MOD_NAME(modifier, "blue", mod_hash, MOD_HASH_BLUE)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BLUE;
}
if (COMPARE_MOD_NAME(modifier, "magenta", mod_hash, MOD_HASH_MAGENTA)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_MAGENTA;
}
if (COMPARE_MOD_NAME(modifier, "cyan", mod_hash, MOD_HASH_CYAN)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_CYAN;
}
if (COMPARE_MOD_NAME(modifier, "white", mod_hash, MOD_HASH_WHITE)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_WHITE;
}
if (COMPARE_MOD_NAME(modifier, "dark_grey", mod_hash, MOD_HASH_DARK_GREY)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLACK;
}
if (COMPARE_MOD_NAME(modifier, "bright_red", mod_hash, MOD_HASH_BRIGHT_RED)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_RED;
}
if (COMPARE_MOD_NAME(
modifier, "bright_green", mod_hash, MOD_HASH_BRIGHT_GREEN)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_GREEN;
}
if (COMPARE_MOD_NAME(
modifier, "bright_yellow", mod_hash, MOD_HASH_BRIGHT_YELLOW)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_YELLOW;
}
if (COMPARE_MOD_NAME(
modifier, "bright_blue", mod_hash, MOD_HASH_BRIGHT_BLUE)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLUE;
}
if (COMPARE_MOD_NAME(
modifier, "bright_magenta", mod_hash, MOD_HASH_BRIGHT_MAGENTA)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_MAGENTA;
}
if (COMPARE_MOD_NAME(
modifier, "bright_cyan", mod_hash, MOD_HASH_BRIGHT_CYAN)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_CYAN;
}
if (COMPARE_MOD_NAME(
modifier, "bright_white", mod_hash, MOD_HASH_BRIGHT_WHITE)) {
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_BRIGHT_WHITE;
}
if (COMPARE_MOD_NAME(modifier, "bg_black", mod_hash, MOD_HASH_BG_BLACK)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BLACK;
}
if (COMPARE_MOD_NAME(modifier, "bg_red", mod_hash, MOD_HASH_BG_RED)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_RED;
}
if (COMPARE_MOD_NAME(modifier, "bg_green", mod_hash, MOD_HASH_BG_GREEN)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_GREEN;
}
if (COMPARE_MOD_NAME(modifier, "bg_yellow", mod_hash, MOD_HASH_BG_YELLOW)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_YELLOW;
}
if (COMPARE_MOD_NAME(modifier, "bg_blue", mod_hash, MOD_HASH_BG_BLUE)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BLUE;
}
if (COMPARE_MOD_NAME(modifier, "bg_magenta", mod_hash, MOD_HASH_BG_MAGENTA)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_MAGENTA;
}
if (COMPARE_MOD_NAME(modifier, "bg_cyan", mod_hash, MOD_HASH_BG_CYAN)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_CYAN;
}
if (COMPARE_MOD_NAME(modifier, "bg_white", mod_hash, MOD_HASH_BG_WHITE)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_WHITE;
}
if (COMPARE_MOD_NAME(
modifier, "bg_dark_grey", mod_hash, MOD_HASH_BG_DARK_GREY)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLACK;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_red", mod_hash, MOD_HASH_BRIGHT_BG_RED)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_RED;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_green", mod_hash,
MOD_HASH_BRIGHT_BG_GREEN)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_GREEN;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_yellow", mod_hash,
MOD_HASH_BRIGHT_BG_YELLOW)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_YELLOW;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_blue", mod_hash, MOD_HASH_BRIGHT_BG_BLUE)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_BLUE;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_magenta", mod_hash,
MOD_HASH_BRIGHT_BG_MAGENTA)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_MAGENTA;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_cyan", mod_hash, MOD_HASH_BRIGHT_BG_CYAN)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_CYAN;
}
if (COMPARE_MOD_NAME(
modifier, "bright_bg_white", mod_hash,
MOD_HASH_BRIGHT_BG_WHITE)) {
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BRIGHT_WHITE;
}
if (COMPARE_MOD_NAME(modifier, "bold", mod_hash, MOD_HASH_BOLD)) {
fmt->vmode.v_attrib |= B_TTY_ATTRIB_BOLD;
}
if (COMPARE_MOD_NAME(modifier, "uline", mod_hash, MOD_HASH_ULINE)) {
fmt->vmode.v_attrib |= B_TTY_ATTRIB_UNDERLINE;
}
if (COMPARE_MOD_NAME(modifier, "italic", mod_hash, MOD_HASH_ITALIC)) {
fmt->vmode.v_attrib |= B_TTY_ATTRIB_ITALIC;
}
if (COMPARE_MOD_NAME(modifier, "invert", mod_hash, MOD_HASH_INVERT)) {
fmt->vmode.v_attrib |= B_TTY_ATTRIB_INVERT;
}
if (COMPARE_MOD_NAME(modifier, "reset", mod_hash, MOD_HASH_RESET)) {
fmt->reset_vmode = true;
fmt->vmode.v_fg.c_mode = B_TTY_COLOUR_NONE;
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_NONE;
fmt->vmode.v_attrib = 0;
}
}
static void format_buffer_putc(struct tty_format_buf *fmt, int c)
{
if (fmt->ptr < TTY_TMPBUF_SIZE - 1) {
fmt->buf[fmt->ptr++] = c;
fmt->buf[fmt->ptr] = '\0';
}
}
static void format_buffer_clear(struct tty_format_buf *fmt)
{
fmt->ptr = 0;
fmt->buf[fmt->ptr] = '\0';
fmt->reset_vmode = false;
}
static void flush_vmode(struct b_tty *tty, struct tty_format_buf *fmt)
{
if (fmt->reset_vmode) {
b_tty_reset_vmode(tty);
} else {
b_tty_set_vmode(tty, &fmt->vmode);
}
}
int b_tty_putc(struct b_tty *tty, enum b_tty_print_flags flags, char c)
{
if (flags & B_TTY_DISABLE_FORMATTING) {
z__b_tty_putc(tty, c);
return c;
}
struct tty_format_buf *fmt = z__b_tty_get_format_buf(tty);
if (c == '[') {
if (!fmt->in_format) {
fmt->in_format = true;
return c;
}
if (fmt->ptr == 0) {
fmt->in_format = false;
z__b_tty_putc(tty, '[');
return c;
}
format_buffer_putc(fmt, c);
return c;
}
if (fmt->in_format && c == ']') {
apply_code_to_vmode(fmt);
format_buffer_clear(fmt);
flush_vmode(tty, fmt);
fmt->in_format = false;
return c;
}
if (fmt->in_format && c == ',') {
apply_code_to_vmode(fmt);
format_buffer_clear(fmt);
return c;
}
if (fmt->in_format) {
format_buffer_putc(fmt, c);
} else {
z__b_tty_putc(tty, c);
}
return c;
}
int b_tty_puts(struct b_tty *tty, enum b_tty_print_flags flags, const char *s)
{
int r = 0;
while (s[r]) {
b_tty_putc(tty, flags, s[r]);
r++;
}
return r;
}
int b_tty_printf(struct b_tty *tty, enum b_tty_print_flags flags, const char *s, ...)
{
va_list arg;
va_start(arg, s);
int r = b_tty_vprintf(tty, flags, s, arg);
va_end(arg);
return r;
}