term: extend tty interface with more features
This commit is contained in:
330
term/tty.c
Normal file
330
term/tty.c
Normal file
@@ -0,0 +1,330 @@
|
||||
#include <blue/term/tty.h>
|
||||
#include <blue/core/hash.h>
|
||||
#include "tty.h"
|
||||
#include "printf.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;
|
||||
uint64_t mod_hash = b_hash_string(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->vmode.v_fg.c_mode = B_TTY_COLOUR_16;
|
||||
fmt->vmode.v_bg.c_mode = B_TTY_COLOUR_16;
|
||||
|
||||
fmt->vmode.v_fg.c_16.value = B_TTY_COLOUR16_WHITE;
|
||||
fmt->vmode.v_bg.c_16.value = B_TTY_COLOUR16_BLACK;
|
||||
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';
|
||||
}
|
||||
|
||||
static void flush_vmode(struct b_tty* tty, struct tty_format_buf* fmt)
|
||||
{
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user