From bf4847d3e028516b0de446e8455d43833983c17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 23 Jul 2019 18:54:58 +0200 Subject: [PATCH] conf: allow the user to configure a fixed cursor color The default is to reverse the foreground/background colors in the cell with the cursor. But, if the user configures a specific set of cursor colors, those will always be used, regardless of other cell attributes (dim, reverse etc). The cursor color is specified as two color values, 'text' and 'cursor'. The block cursor uses the 'cursor' color as background, and the 'text' color for the glyph. All other cursor styles uses the 'cursor' color for the cursor, but uses the cell's foreground color for the glyph (meaning, dim/reverse/etc applies). --- config.c | 64 +++++++++++++++++++++++++++++++++++++++++++----------- config.h | 4 ++++ main.c | 8 +++++++ render.c | 12 ++++++++-- terminal.h | 8 +++++++ 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/config.c b/config.c index c3867d2d..707f7d93 100644 --- a/config.c +++ b/config.c @@ -106,6 +106,30 @@ get_config_path(void) return NULL; } +static bool +str_to_color(const char *s, uint32_t *color, const char *path, int lineno) +{ + if (s == NULL) + return false; + + errno = 0; + char *end = NULL; + unsigned long res = strtoul(s, &end, 16); + + if (errno != 0) { + LOG_ERRNO("%s:%d: invalid color: %s", path, lineno, s); + return false; + } + + if (*end != '\0') { + LOG_ERR("%s:%d: invalid color: %s", path, lineno, s); + return false; + } + + *color = res & 0xffffff; + return true; +} + static bool parse_section_main(const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) @@ -163,21 +187,11 @@ parse_section_colors(const char *key, const char *value, struct config *conf, 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); + uint32_t color_value; + if (!str_to_color(value, &color_value, path, lineno)) return false; - } - if (*end != '\0') { - LOG_ERR("%s:%d: invalid color: %s", path, lineno, value); - return false; - } - - *color = res & 0xffffff; + *color = color_value; return true; } @@ -199,6 +213,26 @@ parse_section_cursor(const char *key, const char *value, struct config *conf, } } + else if (strcmp(key, "color") == 0) { + char *value_copy = strdup(value); + const char *text = strtok(value_copy, " "); + const char *cursor = strtok(NULL, " "); + + uint32_t text_color, cursor_color; + if (text == NULL || cursor == NULL || + !str_to_color(text, &text_color, path, lineno) || + !str_to_color(cursor, &cursor_color, path, lineno)) + { + LOG_ERR("%s:%d: invalid cursor colors: %s", path, lineno, value); + free(value_copy); + return false; + } + + conf->cursor.color.text = 1 << 31 | text_color; + conf->cursor.color.cursor = 1 << 31 | cursor_color; + free(value_copy); + } + else { LOG_ERR("%s:%d: invalid key: %s", path, lineno, key); return false; @@ -388,6 +422,10 @@ config_load(struct config *conf) .cursor = { .style = CURSOR_BLOCK, + .color = { + .text = 0, + .cursor = 0, + }, }, }; diff --git a/config.h b/config.h index 85ce15c1..68d6f0a1 100644 --- a/config.h +++ b/config.h @@ -19,6 +19,10 @@ struct config { struct { enum cursor_style style; + struct { + uint32_t text; + uint32_t cursor; + } color; } cursor; }; diff --git a/main.c b/main.c index 917eec9d..d785024c 100644 --- a/main.c +++ b/main.c @@ -373,6 +373,14 @@ main(int argc, char *const *argv) }, .default_cursor_style = conf.cursor.style, .cursor_style = conf.cursor.style, + .default_cursor_color = { + .text = conf.cursor.color.text, + .cursor = conf.cursor.color.cursor, + }, + .cursor_color = { + .text = conf.cursor.color.text, + .cursor = conf.cursor.color.cursor, + }, .selection = { .start = {-1, -1}, .end = {-1, -1}, diff --git a/render.c b/render.c index 3e5730e0..16bc19b9 100644 --- a/render.c +++ b/render.c @@ -194,6 +194,13 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, if (cell->attrs.dim) color_dim(&fg); + if (block_cursor && term->cursor_color.text >> 31) { + /* User configured cursor color overrides all attributes */ + assert(term->cursor_color.cursor >> 31); + fg = color_hex_to_rgb(term->cursor_color.text); + bg = color_hex_to_rgb(term->cursor_color.cursor); + } + /* Background */ cairo_set_source_rgb(buf->cairo, bg.r, bg.g, bg.b); cairo_rectangle(buf->cairo, x, y, width, height); @@ -201,11 +208,12 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, /* Non-block cursors */ if (has_cursor) { + struct rgb cursor_color = color_hex_to_rgb(term->cursor_color.cursor); if (term->cursor_style == CURSOR_BAR) - draw_bar(term, buf, fg, x, y); + draw_bar(term, buf, cursor_color, x, y); else if (term->cursor_style == CURSOR_UNDERLINE) draw_underline( - term, buf, attrs_to_font(term, &cell->attrs), fg, x, y); + term, buf, attrs_to_font(term, &cell->attrs), cursor_color, x, y); } if (cell->attrs.blink && !term->blink.active) { diff --git a/terminal.h b/terminal.h index 94e99215..49a24803 100644 --- a/terminal.h +++ b/terminal.h @@ -296,6 +296,14 @@ struct terminal { enum cursor_style default_cursor_style; enum cursor_style cursor_style; bool cursor_blinking; + struct { + uint32_t text; + uint32_t cursor; + } default_cursor_color; + struct { + uint32_t text; + uint32_t cursor; + } cursor_color; uint32_t input_serial; struct {