From 63522a14fce9aca5a3aabb068e6a42dd8d817032 Mon Sep 17 00:00:00 2001 From: cowmonk Date: Tue, 21 Jan 2025 18:31:58 -0700 Subject: [PATCH] 256-color SUPPORT + extra stuff too ig very epico update, makes it much much more usable --- config.h | 3 ++ cowterm.c | 106 +++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/config.h b/config.h index 7c5893c..8bff5b7 100644 --- a/config.h +++ b/config.h @@ -5,6 +5,9 @@ // Change as suited for your monitor #define REFRESH_INTERVAL 16666 +// Support for 256 colors +#define COLOR_256_SUPPORT 1 // Who the hell wants to use 16 colors in 2025? + // Colors are just configured like RBG, if you don't recognize // this color format, search it up and find it out yourself static const unsigned long int RED = 0xFF0000; diff --git a/cowterm.c b/cowterm.c index fed3046..fc84ae7 100644 --- a/cowterm.c +++ b/cowterm.c @@ -68,6 +68,7 @@ static int using_alternate = 0; #define ATTR_BOLD (1 << 0) #define ATTR_ITALIC (1 << 1) #define ATTR_REVERSE (1 << 2) +#define ATTR_UNDERLINE (1 << 3) #define ATTR_DIM (1 << 4) #define ATTR_BLINK (1 << 5) @@ -343,6 +344,11 @@ static void draw_char(Display *display, Drawable d, int x, int y) { XSetFont(display, gc, font->fid); XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 4, str, 1); + + if (attr & ATTR_UNDERLINE) { + XDrawLine(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 1, + (x + 1) * CHAR_WIDTH - 1, (y + 1) * CHAR_HEIGHT - 1); + } } static void draw_terminal(Display *display, Window window) { @@ -718,6 +724,28 @@ static unsigned long get_bright_ansi_color(int index) { return colors[index & 7]; } +#if COLOR_256_SUPPORT +static unsigned long get_256_color(int index) { + // Basic 16 colors + if (index < 16) + return index < 8 ? get_ansi_color(index) : get_bright_ansi_color(index - 8); + + // 216 color cube + if (index < 232) { + index -= 16; + int r = (index / 36) * 51; + int g = ((index % 36) / 6) * 51; + int b = (index % 6) * 51; + return (r << 16) | (g << 8) | b; + } + + // Grayscale + index -= 232; + int gray = index * 10 + 8; + return (gray << 16) | (gray << 8) | gray; +} +#endif + // Handles those pesky ANSI color escape codes that terminals use. // When \033[m is sent to the terminal, it changes text color: // 30 = Black 31 = Red 32 = Green 33 = Yellow @@ -1043,7 +1071,8 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len, break; } for (int i = 0; i < (int)param_idx; i++) { - if (params[i] == 0) { // Reset Everything + switch (params[i]) { + case 0: /* Reset */ current_color = XWhitePixel(display, DefaultScreen(display)); current_bg_color = XBlackPixel(display, DefaultScreen(display)); current_attr = 0; @@ -1054,38 +1083,69 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len, attr_buffer[cursor_y][x] = current_attr; } } - } else if (params[i] == 1) { // Apply ATTRS + break; + case 1: // Bold current_attr |= ATTR_BOLD; - } else if (params[i] == 2) { + break; + case 2: // Dim current_attr |= ATTR_DIM; - } else if (params[i] == 3) { + break; + case 3: // Italic current_attr |= ATTR_ITALIC; - } else if (params[i] == 5) { // Slow blink + break; + case 5: // Blink (slow) current_attr |= ATTR_BLINK; - } else if (params[i] == 7) { + break; + case 7: // Reverse current_attr |= ATTR_REVERSE; - } else if (params[i] == 22) { // Reset ATTRS - current_attr &= ~ATTR_BOLD; - } else if (params[i] == 23) { + break; + case 22: // Reset Bold and Dim + current_attr &= ~(ATTR_BOLD | ATTR_DIM); + break; + case 23: // Reset Italic current_attr &= ~ATTR_ITALIC; - } else if (params[i] == 25) { + break; + case 25: // Reset Blink current_attr &= ~ATTR_BLINK; - } else if (params[i] == 27) { + break; + case 27: // Reset Reverse current_attr &= ~ATTR_REVERSE; - } else if (params[i] >= 30 && params[i] <= 37) { // Foreground colors - current_color = get_ansi_color(params[i] - 30); - } else if (params[i] == 39) { // Reset foreground color + break; + case 38: // Extended foreground color +#if COLOR_256_SUPPORT + if (i + 2 < (int)param_idx && params[i + 1] == 5) { + current_color = get_256_color(params[i + 2]); + i += 2; + } +#endif + break; + case 39: // Default foreground current_color = XWhitePixel(display, DefaultScreen(display)); - } else if (params[i] >= 40 && params[i] <= 47) { // Background colors - current_bg_color = get_ansi_color(params[i] - 40); - } else if (params[i] == 49) { // Reset background color + break; + case 48: // Extended background color +#if COLOR_256_SUPPORT + if (i + 2 < (int)param_idx && params[i + 1] == 5) { + current_bg_color = get_256_color(params[i + 2]); + i += 2; + } +#endif + break; + case 49: // Default background color current_bg_color = XBlackPixel(display, DefaultScreen(display)); - } else if (params[i] >= 90 && params[i] <= 97) { // Bright foreground - current_color = get_bright_ansi_color(params[i] - 90); - } else if (params[i] >= 100 && params[i] <= 107) { // Bright background - current_bg_color = get_bright_ansi_color(params[i] - 100); + break; + default: + if (params[i] >= 30 && params[i] <= 37) + current_color = get_ansi_color(params[i] - 30); + else if (params[i] >= 40 && params[i] <= 47) + current_bg_color = get_ansi_color(params[i] - 40); + else if (params[i] >= 90 && params[i] <= 97) + current_color = get_bright_ansi_color(params[i] - 90); + else if (params[i] >= 100 && params[i] <= 107) + current_bg_color = get_bright_ansi_color(params[i] - 100); + break; } } + needs_refresh = 1; break; } } @@ -1343,7 +1403,11 @@ int main(void) { close(slave); char *sh = getenv("SHELL"); +#if COLOR_256_SUPPORT setenv("TERM", "xterm-256color", 1); +#else + setenv("TERM", "xterm", 1); +#endif execl(sh ? sh : "/bin/sh", sh ? sh : "sh", 0); return 1; }