diff --git a/config.c b/config.c index 6d234264..6b9663e7 100644 --- a/config.c +++ b/config.c @@ -16,6 +16,31 @@ #define LOG_ENABLE_DBG 0 #include "log.h" +static const uint32_t default_foreground = 0xdcdccc; +static const uint32_t default_background = 0x111111; + +static const uint32_t default_regular[] = { + 0x000000, + 0xcc9393, + 0x7f9f7f, + 0xd0bf8f, + 0x6ca0a3, + 0xdc8cc3, + 0x93e0e3, + 0xdcdccc, +}; + +static const uint32_t default_bright[] = { + 0x000000, + 0xdca3a3, + 0xbfebbf, + 0xf0dfaf, + 0x8cd0d3, + 0xdc8cc3, + 0x93e0e3, + 0xffffff, +}; + static char * get_shell(void) { @@ -108,11 +133,60 @@ parse_section_main(const char *key, const char *value, struct config *conf, return true; } +static bool +parse_section_colors(const char *key, const char *value, struct config *conf, + const char *path, unsigned lineno) +{ + uint32_t *color = NULL; + + if (strcmp(key, "foreground") == 0) color = &conf->colors.fg; + else if (strcmp(key, "background") == 0) color = &conf->colors.bg; + else if (strcmp(key, "regular0") == 0) color = &conf->colors.regular[0]; + else if (strcmp(key, "regular1") == 0) color = &conf->colors.regular[1]; + else if (strcmp(key, "regular2") == 0) color = &conf->colors.regular[2]; + else if (strcmp(key, "regular3") == 0) color = &conf->colors.regular[3]; + else if (strcmp(key, "regular4") == 0) color = &conf->colors.regular[4]; + else if (strcmp(key, "regular5") == 0) color = &conf->colors.regular[5]; + else if (strcmp(key, "regular6") == 0) color = &conf->colors.regular[6]; + else if (strcmp(key, "regular7") == 0) color = &conf->colors.regular[7]; + else if (strcmp(key, "bright0") == 0) color = &conf->colors.bright[0]; + else if (strcmp(key, "bright1") == 0) color = &conf->colors.bright[1]; + else if (strcmp(key, "bright2") == 0) color = &conf->colors.bright[2]; + else if (strcmp(key, "bright3") == 0) color = &conf->colors.bright[3]; + else if (strcmp(key, "bright4") == 0) color = &conf->colors.bright[4]; + else if (strcmp(key, "bright5") == 0) color = &conf->colors.bright[5]; + else if (strcmp(key, "bright6") == 0) color = &conf->colors.bright[6]; + else if (strcmp(key, "bright7") == 0) color = &conf->colors.bright[7]; + + else { + LOG_ERR("%s:%d: invalid key: %s", path, lineno, key); + return false; + } + + errno = 0; + char *end = NULL; + unsigned long res = strtoul(value, &end, 16); + + if (errno != 0) { + LOG_ERRNO("%s:%d: invalid color: %s", path, lineno, value); + return false; + } + + if (*end != '\0') { + LOG_ERR("%s:%d: invalid color: %s", path, lineno, value); + return false; + } + + *color = res & 0xffffff; + return true; +} + static bool parse_config_file(FILE *f, struct config *conf, const char *path) { enum section { SECTION_MAIN, + SECTION_COLORS, } section = SECTION_MAIN; /* Function pointer, called for each key/value line */ @@ -123,11 +197,13 @@ parse_config_file(FILE *f, struct config *conf, const char *path) /* Maps sections to line parser functions */ static const parser_fun_t section_parser_map[] = { [SECTION_MAIN] = &parse_section_main, + [SECTION_COLORS] = &parse_section_colors, }; #if defined(_DEBUG) && defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG static const char *const section_names[] = { [SECTION_MAIN] = "main", + [SECTION_COLORS] = "colors", }; #endif @@ -150,10 +226,25 @@ parse_config_file(FILE *f, struct config *conf, const char *path) break; } - /* No sections yet */ - if (line[0] == '[' && line[strlen(line) - 1] == ']') { - assert(false); - return false; + if (line[0] == '[') { + char *end = strchr(line, ']'); + if (end == NULL) { + LOG_ERR("%s:%d: syntax error: %s", path, lineno, line); + free(line); + return false; + } + + *end = '\0'; + + if (strcmp(&line[1], "colors") == 0) + section = SECTION_COLORS; + else { + LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &line[1]); + free(line); + return false; + } + + continue; } char *key = strtok(line, "="); @@ -219,6 +310,31 @@ config_load(struct config *conf) .term = strdup("foot"), .shell = get_shell(), .font = strdup("monospace"), + + .colors = { + .fg = default_foreground, + .bg = default_background, + .regular = { + default_regular[0], + default_regular[1], + default_regular[2], + default_regular[3], + default_regular[4], + default_regular[5], + default_regular[6], + default_regular[7], + }, + .bright = { + default_bright[0], + default_bright[1], + default_bright[2], + default_bright[3], + default_bright[4], + default_bright[5], + default_bright[6], + default_bright[7], + }, + }, }; char *path = get_config_path(); diff --git a/config.h b/config.h index fdca3c34..0db93269 100644 --- a/config.h +++ b/config.h @@ -1,11 +1,19 @@ #pragma once +#include #include struct config { char *term; char *shell; char *font; + + struct { + uint32_t fg; + uint32_t bg; + uint32_t regular[8]; + uint32_t bright[8]; + } colors; }; bool config_load(struct config *conf); diff --git a/csi.c b/csi.c index 7709dfd6..4d1921bd 100644 --- a/csi.c +++ b/csi.c @@ -18,101 +18,37 @@ #define min(x, y) ((x) < (y) ? (x) : (y)) -#if 0 -static const struct rgb colors_regular[] = { - {0.000000, 0.000000, 0.000000}, /* 0x000000 */ - {0.800000, 0.576471, 0.576471}, /* 0xcc9393 */ - {0.498039, 0.623529, 0.498039}, /* 0x7f9f7f */ - {0.815686, 0.749020, 0.560784}, /* 0xd0bf8f */ - {0.423529, 0.627451, 0.639216}, /* 0x6ca0a3 */ - {0.862745, 0.549020, 0.764706}, /* 0xdc8cc3 */ - {0.576471, 0.878431, 0.890196}, /* 0x93e0e3 */ - {0.862745, 0.862745, 0.800000}, /* 0xdcdccc */ -}; - -static const struct rgb colors_bright[] = { - {0.000000, 0.000000, 0.000000}, /* 0x000000 */ - {0.862745, 0.639216, 0.639216}, /* 0xdca3a3 */ - {0.749020, 0.921569, 0.749020}, /* 0xbfebbf */ - {0.941176, 0.874510, 0.686275}, /* 0xf0dfaf */ - {0.549020, 0.815686, 0.827451}, /* 0x8cd0d3 */ - {0.862745, 0.549020, 0.764706}, /* 0xdc8cc3 */ - {0.576471, 0.878431, 0.890196}, /* 0x93e0e3 */ - {1.000000, 1.000000, 1.000000}, /* 0xffffff */ -}; - -static struct rgb colors256[256]; -#else -static const uint32_t colors_regular[] = { - 0x000000, - 0xcc9393, - 0x7f9f7f, - 0xd0bf8f, - 0x6ca0a3, - 0xdc8cc3, - 0x93e0e3, - 0xdcdccc, -}; - -static const uint32_t colors_bright[] = { - 0x000000, - 0xdca3a3, - 0xbfebbf, - 0xf0dfaf, - 0x8cd0d3, - 0xdc8cc3, - 0x93e0e3, - 0xffffff, -}; - static uint32_t colors256[256]; -#endif static void __attribute__((constructor)) initialize_colors256(void) { +#if 0 /* pick colors from term struct instead, since they can be changed runtime */ for (size_t i = 0; i < 8; i++) colors256[i] = colors_regular[i]; for (size_t i = 0; i < 8; i++) colors256[8 + i] = colors_bright[i]; +#endif for (size_t r = 0; r < 6; r++) { for (size_t g = 0; g < 6; g++) { for (size_t b = 0; b < 6; b++) { -#if 0 - colors256[16 + r * 6 * 6 + g * 6 + b] = (struct rgb) { - r * 51 / 255.0, - g * 51 / 255.0, - b * 51 / 255.0, - }; -#else colors256[16 + r * 6 * 6 + g * 6 + b] = r * 51 << 16 | g * 51 << 8 | b * 51; -#endif } } } - for (size_t i = 0; i < 24; i++){ -#if 0 - colors256[232 + i] = (struct rgb) { - i * 11 / 255.0, - i * 11 / 255.0, - i * 11 / 255.0, - }; -#else - /* TODO: i + 1? */ + for (size_t i = 0; i < 24; i++) colors256[232 + i] = i * 11 << 16 | i * 11 << 8 | i * 11; -#endif - } } static void sgr_reset(struct terminal *term) { memset(&term->vt.attrs, 0, sizeof(term->vt.attrs)); - term->vt.attrs.foreground = term->foreground; - term->vt.attrs.background = term->background; + term->vt.attrs.foreground = term->colors.fg; + term->vt.attrs.background = term->colors.bg; } static const char * @@ -190,7 +126,7 @@ csi_sgr(struct terminal *term) case 35: case 36: case 37: - term->vt.attrs.foreground = 1 << 31 | colors_regular[param - 30]; + term->vt.attrs.foreground = 1 << 31 | term->colors.regular[param - 30]; break; case 38: { @@ -198,7 +134,14 @@ csi_sgr(struct terminal *term) term->vt.params.v[i + 1].value == 5) { uint8_t idx = term->vt.params.v[i + 2].value; - term->vt.attrs.foreground = 1 << 31 | colors256[idx]; + uint32_t color; + if (idx < 8) + color = term->colors.regular[idx]; + else if (idx < 16) + color = term->colors.bright[idx - 8]; + else + color = colors256[idx]; + term->vt.attrs.foreground = 1 << 31 | color; i += 2; } @@ -252,7 +195,7 @@ csi_sgr(struct terminal *term) case 45: case 46: case 47: - term->vt.attrs.background = 1 << 31 | colors_regular[param - 40]; + term->vt.attrs.background = 1 << 31 | term->colors.regular[param - 40]; break; case 48: { @@ -260,7 +203,15 @@ csi_sgr(struct terminal *term) term->vt.params.v[i + 1].value == 5) { uint8_t idx = term->vt.params.v[i + 2].value; - term->vt.attrs.background = 1 << 31 | colors256[idx]; + uint32_t color; + + if (idx < 8) + color = term->colors.regular[idx]; + else if (idx < 16) + color = term->colors.bright[idx - 8]; + else + color = colors256[idx]; + term->vt.attrs.background = 1 << 31 | color; i += 2; } @@ -314,7 +265,7 @@ csi_sgr(struct terminal *term) case 95: case 96: case 97: - term->vt.attrs.foreground = 1 << 31 | colors_bright[param - 90]; + term->vt.attrs.foreground = 1 << 31 | term->colors.bright[param - 90]; break; /* Regular background colors */ @@ -326,7 +277,7 @@ csi_sgr(struct terminal *term) case 105: case 106: case 107: - term->vt.attrs.background = 1 << 31 | colors_bright[param - 100]; + term->vt.attrs.background = 1 << 31 | term->colors.bright[param - 100]; break; default: diff --git a/main.c b/main.c index 0c618d39..aedc1a29 100644 --- a/main.c +++ b/main.c @@ -36,14 +36,6 @@ #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) -#if 0 -static const struct rgb default_foreground = {0.86, 0.86, 0.86}; -static const struct rgb default_background = {0.067, 0.067, 0.067}; -#else -static const uint32_t default_foreground = 0xdcdccc; -static const uint32_t default_background = 0x111111; -#endif - static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { @@ -335,8 +327,8 @@ main(int argc, char *const *argv) .vt = { .state = 1, /* STATE_GROUND */ .attrs = { - .foreground = default_foreground, - .background = default_background, + //.foreground = conf.colors.fg, + //.background = conf.colors.bg }, }, .kbd = { @@ -346,8 +338,30 @@ main(int argc, char *const *argv) .cmd = REPEAT_STOP, }, }, - .foreground = default_foreground, - .background = default_background, + .colors = { + .default_fg = conf.colors.fg, + .default_bg = conf.colors.bg, + .default_regular = { + conf.colors.regular[0], + conf.colors.regular[1], + conf.colors.regular[2], + conf.colors.regular[3], + conf.colors.regular[4], + conf.colors.regular[5], + conf.colors.regular[6], + conf.colors.regular[7], + }, + .default_bright = { + conf.colors.bright[0], + conf.colors.bright[1], + conf.colors.bright[2], + conf.colors.bright[3], + conf.colors.bright[4], + conf.colors.bright[5], + conf.colors.bright[6], + conf.colors.bright[7], + }, + }, .selection = { .start = {-1, -1}, .end = {-1, -1}, @@ -357,6 +371,14 @@ main(int argc, char *const *argv) .grid = &term.normal, }; + /* Initialize 'current' colors from the default colors */ + term.colors.fg = term.colors.default_fg; + term.colors.bg = term.colors.default_bg; + for (size_t i = 0; i < 8; i++) { + term.colors.regular[i] = term.colors.default_regular[i]; + term.colors.bright[i] = term.colors.default_bright[i]; + } + if (term.ptmx == -1) { LOG_ERRNO("failed to open pseudo terminal"); goto out; diff --git a/osc.c b/osc.c index bd693a8d..02f393b6 100644 --- a/osc.c +++ b/osc.c @@ -18,7 +18,7 @@ osc_query(struct terminal *term, unsigned param) switch (param) { case 10: case 11: { - uint32_t color = param == 10 ? term->foreground : term->background; + uint32_t color = param == 10 ? term->colors.fg : term->colors.bg; uint8_t r = (color >> 16) & 0xff; uint8_t g = (color >> 8) & 0xff; uint8_t b = (color >> 0) & 0xff; diff --git a/render.c b/render.c index 5b3c2956..f9c7fbca 100644 --- a/render.c +++ b/render.c @@ -105,10 +105,10 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, uint32_t _fg = cell->attrs.foreground >> 31 ? cell->attrs.foreground - : !term->reverse ? term->foreground : term->background; + : !term->reverse ? term->colors.fg : term->colors.bg; uint32_t _bg = cell->attrs.background >> 31 ? cell->attrs.background - : !term->reverse ? term->background : term->foreground; + : !term->reverse ? term->colors.bg : term->colors.fg; /* If *one* is set, we reverse */ if (has_cursor ^ cell->attrs.reverse ^ is_selected) { @@ -307,7 +307,7 @@ grid_render(struct terminal *term) int rmargin_width = term->width - rmargin; int bmargin_height = term->height - bmargin; - uint32_t _bg = !term->reverse ? term->background : term->foreground; + uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg; struct rgb bg = color_hex_to_rgb(_bg); cairo_set_source_rgb(buf->cairo, bg.r, bg.g, bg.b); diff --git a/terminal.h b/terminal.h index c0d68f21..c757065a 100644 --- a/terminal.h +++ b/terminal.h @@ -259,8 +259,17 @@ struct terminal { bool print_needs_wrap; struct scroll_region scroll_region; - uint32_t foreground; - uint32_t background; + struct { + uint32_t fg; + uint32_t bg; + uint32_t regular[8]; + uint32_t bright[8]; + + uint32_t default_fg; + uint32_t default_bg; + uint32_t default_regular[8]; + uint32_t default_bright[8]; + } colors; struct { int col;