381 lines
9.7 KiB
C
381 lines
9.7 KiB
C
#include "print.h"
|
|
|
|
#include <blue/core/hash.h>
|
|
#include <blue/term.h>
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#define F_BLACK "[black]"
|
|
#define F_RED "[red]"
|
|
#define F_YEL "[yellow]"
|
|
#define F_CYN "[cyan]"
|
|
|
|
#define F_BLACK_BOLD "[bold,black]"
|
|
#define F_RED_BOLD "[bold,red]"
|
|
#define F_YEL_BOLD "[bold,yellow]"
|
|
#define F_CYN_BOLD "[bold,cyan]"
|
|
|
|
#define F_BLACK_BG "[bg_black]"
|
|
#define F_RED_BG "[bg_reg]"
|
|
#define F_YEL_BG "[bg_yellow]"
|
|
#define F_CYN_BG "[bg_cyan]"
|
|
|
|
#define F_RESET "[reset]"
|
|
|
|
typedef b_status (*print_function)(FILE *fp, const char *s);
|
|
|
|
#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_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_BOLD 0xcd32ea9bc6b26ff6
|
|
#define MOD_HASH_BRIGHT 0xb5cca637f5a2b385
|
|
#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))
|
|
|
|
b_status b_term_get_dimensions(FILE *fp, unsigned int *w, unsigned int *h)
|
|
{
|
|
return z__b_stream_dimensions(fp, w, h) == 0 ? B_SUCCESS
|
|
: B_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
static void apply_modifier(FILE *fp, const char *modifier, unsigned int *mod_flagp)
|
|
{
|
|
uint64_t mod_hash = b_hash_string(modifier);
|
|
unsigned int mod_flags = *mod_flagp;
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "black", mod_hash, MOD_HASH_BLACK)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BLACK;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "red", mod_hash, MOD_HASH_RED)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_RED;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "green", mod_hash, MOD_HASH_GREEN)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_GREEN;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "yellow", mod_hash, MOD_HASH_YELLOW)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_GREEN;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "blue", mod_hash, MOD_HASH_BLUE)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "magenta", mod_hash, MOD_HASH_MAGENTA)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "cyan", mod_hash, MOD_HASH_CYAN)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_GREEN | Z__B_STREAM_MOD_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "white", mod_hash, MOD_HASH_WHITE)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_FG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_RED | Z__B_STREAM_MOD_GREEN
|
|
| Z__B_STREAM_MOD_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_black", mod_hash, MOD_HASH_BG_BLACK)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_BLACK;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_red", mod_hash, MOD_HASH_BG_RED)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_RED;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_green", mod_hash, MOD_HASH_BG_GREEN)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_GREEN;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_yellow", mod_hash, MOD_HASH_BG_YELLOW)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_GREEN;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_blue", mod_hash, MOD_HASH_BG_BLUE)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_magenta", mod_hash, MOD_HASH_BG_MAGENTA)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_cyan", mod_hash, MOD_HASH_BG_CYAN)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_GREEN | Z__B_STREAM_MOD_BG_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bg_white", mod_hash, MOD_HASH_BG_WHITE)) {
|
|
mod_flags = Z__B_STREAM_MOD_CLEAR_BG_COLOUR(mod_flags);
|
|
mod_flags |= Z__B_STREAM_MOD_BG_RED | Z__B_STREAM_MOD_BG_GREEN
|
|
| Z__B_STREAM_MOD_BG_BLUE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bold", mod_hash, MOD_HASH_BOLD)) {
|
|
mod_flags |= Z__B_STREAM_MOD_BOLD;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "bright", mod_hash, MOD_HASH_BRIGHT)) {
|
|
mod_flags |= Z__B_STREAM_MOD_BRIGHT;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "uline", mod_hash, MOD_HASH_ULINE)) {
|
|
mod_flags |= Z__B_STREAM_MOD_ULINE;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "italic", mod_hash, MOD_HASH_ITALIC)) {
|
|
mod_flags |= Z__B_STREAM_MOD_ITALIC;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "invert", mod_hash, MOD_HASH_INVERT)) {
|
|
mod_flags |= Z__B_STREAM_MOD_INVERT;
|
|
}
|
|
|
|
if (COMPARE_MOD_NAME(modifier, "reset", mod_hash, MOD_HASH_RESET)) {
|
|
mod_flags = Z__B_STREAM_MOD_RESET;
|
|
}
|
|
|
|
*mod_flagp = mod_flags;
|
|
}
|
|
|
|
static int print(FILE *fp, const char *str)
|
|
{
|
|
int len = 0;
|
|
char ctrl_buf[128];
|
|
unsigned int ctrl_len = 0;
|
|
|
|
for (size_t i = 0; str[i];) {
|
|
char c = str[i++];
|
|
|
|
if (c != '[') {
|
|
fputc(c, fp);
|
|
len++;
|
|
continue;
|
|
}
|
|
|
|
c = str[i++];
|
|
|
|
if (c == '[') {
|
|
fputc(c, fp);
|
|
len++;
|
|
continue;
|
|
}
|
|
|
|
ctrl_buf[ctrl_len++] = c;
|
|
unsigned int mod_flags = 0;
|
|
|
|
while (true) {
|
|
c = str[i++];
|
|
|
|
if (isspace(c)) {
|
|
continue;
|
|
}
|
|
|
|
if (c == '\0') {
|
|
break;
|
|
}
|
|
|
|
if (c == ']') {
|
|
ctrl_buf[ctrl_len] = '\0';
|
|
apply_modifier(fp, ctrl_buf, &mod_flags);
|
|
ctrl_len = 0;
|
|
ctrl_buf[0] = '\0';
|
|
break;
|
|
}
|
|
|
|
if (c == ',') {
|
|
ctrl_buf[ctrl_len] = '\0';
|
|
apply_modifier(fp, ctrl_buf, &mod_flags);
|
|
ctrl_len = 0;
|
|
ctrl_buf[0] = '\0';
|
|
continue;
|
|
}
|
|
|
|
if (ctrl_len < sizeof ctrl_buf - 1) {
|
|
ctrl_buf[ctrl_len++] = c;
|
|
}
|
|
}
|
|
|
|
z__b_stream_set_modifier(fp, mod_flags);
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
static int print_no_ansi(FILE *fp, const char *str)
|
|
{
|
|
int out = 0;
|
|
|
|
for (size_t i = 0; str[i]; i++) {
|
|
if (str[i] != '\033') {
|
|
fputc(str[i], fp);
|
|
out++;
|
|
continue;
|
|
}
|
|
|
|
while (str[i] && !isalpha(str[i])) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
static b_status print_normal(FILE *fp, const char *s)
|
|
{
|
|
return B_SUCCESS;
|
|
}
|
|
|
|
static b_status print_i(FILE *fp, const char *s)
|
|
{
|
|
b_paragraph_format format = {0};
|
|
format.p_left_margin = 5;
|
|
format.p_right_margin = 5;
|
|
format.p_flags = B_PARAGRAPH_DONT_INDENT_FIRST_LINE
|
|
| B_PARAGRAPH_MULTI_LINE_BREAK;
|
|
|
|
// printf(F_CYN_BG F_BLACK " i " F_RESET " ");
|
|
b_fprintf(fp, F_CYN_BOLD " i:" F_RESET " ");
|
|
b_print_paragraph(s, fp, &format);
|
|
|
|
return B_SUCCESS;
|
|
}
|
|
|
|
static b_status print_warn(FILE *fp, const char *s)
|
|
{
|
|
b_paragraph_format format = {0};
|
|
format.p_left_margin = 5;
|
|
format.p_right_margin = 5;
|
|
format.p_flags = B_PARAGRAPH_DONT_INDENT_FIRST_LINE
|
|
| B_PARAGRAPH_MULTI_LINE_BREAK;
|
|
|
|
// printf(F_YEL_BG F_BLACK " Warn " F_RESET " ");
|
|
b_fprintf(fp, F_YEL_BOLD " !!" F_RESET " ");
|
|
b_print_paragraph(s, fp, &format);
|
|
|
|
return B_SUCCESS;
|
|
}
|
|
|
|
static b_status print_err(FILE *fp, const char *s)
|
|
{
|
|
b_paragraph_format format = {0};
|
|
format.p_left_margin = 5;
|
|
format.p_right_margin = 5;
|
|
format.p_flags = B_PARAGRAPH_DONT_INDENT_FIRST_LINE
|
|
| B_PARAGRAPH_MULTI_LINE_BREAK;
|
|
|
|
// printf(F_RED_BG F_BLACK " Err " F_RESET " ");
|
|
b_fprintf(fp, F_RED_BOLD "Err:" F_RESET " ");
|
|
b_print_paragraph(s, fp, &format);
|
|
|
|
return B_SUCCESS;
|
|
}
|
|
|
|
static print_function format_printers[] = {
|
|
[B_PRINT_NORMAL] = print_normal,
|
|
[B_PRINT_I] = print_i,
|
|
[B_PRINT_WARN] = print_warn,
|
|
[B_PRINT_ERR] = print_err,
|
|
};
|
|
static size_t nr_format_printers
|
|
= sizeof format_printers / sizeof format_printers[B_PRINT_NORMAL];
|
|
|
|
b_status b_print(b_print_format format, const char *str, ...)
|
|
{
|
|
char buf[1024];
|
|
|
|
va_list arg;
|
|
va_start(arg, str);
|
|
vsnprintf(buf, sizeof buf, str, arg);
|
|
va_end(arg);
|
|
|
|
if (format >= nr_format_printers) {
|
|
return B_ERR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
print_function printer = format_printers[format];
|
|
if (!printer) {
|
|
return B_ERR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
return printer(stdout, buf);
|
|
}
|
|
|
|
static int b_vfprintf(FILE *fp, const char *format, va_list arg)
|
|
{
|
|
char str[1024];
|
|
|
|
vsnprintf(str, sizeof str, format, arg);
|
|
|
|
if (z__b_stream_is_tty(fp)) {
|
|
return print(fp, str);
|
|
}
|
|
|
|
return print_no_ansi(fp, str);
|
|
}
|
|
|
|
int b_fputs(const char *str, FILE *fp)
|
|
{
|
|
if (z__b_stream_is_tty(fp)) {
|
|
return print(fp, str);
|
|
}
|
|
|
|
return print_no_ansi(fp, str);
|
|
}
|
|
|
|
int b_printf(const char *format, ...)
|
|
{
|
|
va_list arg;
|
|
va_start(arg, format);
|
|
int len = b_vfprintf(stdout, format, arg);
|
|
va_end(arg);
|
|
|
|
return len;
|
|
}
|
|
|
|
int b_fprintf(FILE *fp, const char *format, ...)
|
|
{
|
|
va_list arg;
|
|
va_start(arg, format);
|
|
int len = b_vfprintf(fp, format, arg);
|
|
va_end(arg);
|
|
|
|
return len;
|
|
}
|