From 555ff00a30b70cb84a767b60e3a5c7015815feae Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 19 Sep 2014 15:37:31 -0700 Subject: [PATCH] Initial work to support for term-24bit ("true color") --- color.cpp | 18 ++++++++++++------ color.h | 11 +++++++++-- env.cpp | 2 +- fish.cpp | 2 +- input.cpp | 19 ++++++++++++++++--- input.h | 4 ++-- output.cpp | 19 ++++++++++--------- output.h | 12 +++++++++--- screen.cpp | 2 +- 9 files changed, 61 insertions(+), 28 deletions(-) diff --git a/color.cpp b/color.cpp index 884410d61..64beaa20e 100644 --- a/color.cpp +++ b/color.cpp @@ -125,7 +125,7 @@ bool rgb_color_t::try_parse_rgb(const wcstring &name) { int val = parse_hex_digit(name.at(digit_idx++)); if (val < 0) break; - data.rgb[i] = val*16+val; + data.color.rgb[i] = val*16+val; } success = (i == 3); } @@ -137,7 +137,7 @@ bool rgb_color_t::try_parse_rgb(const wcstring &name) int hi = parse_hex_digit(name.at(digit_idx++)); int lo = parse_hex_digit(name.at(digit_idx++)); if (lo < 0 || hi < 0) break; - data.rgb[i] = hi*16+lo; + data.color.rgb[i] = hi*16+lo; } success = (i == 3); } @@ -298,7 +298,13 @@ static unsigned char term256_color_for_rgb(const unsigned char rgb[3]) unsigned char rgb_color_t::to_term256_index() const { assert(type == type_rgb); - return term256_color_for_rgb(data.rgb); + return term256_color_for_rgb(data.color.rgb); +} + +color24_t rgb_color_t::to_color24() const +{ + assert(type == type_rgb); + return data.color; } unsigned char rgb_color_t::to_name_index() const @@ -310,7 +316,7 @@ unsigned char rgb_color_t::to_name_index() const } else if (type == type_rgb) { - return term8_color_for_rgb(data.rgb); + return term8_color_for_rgb(data.color.rgb); } else { @@ -327,7 +333,7 @@ void rgb_color_t::parse(const wcstring &str) if (! success) success = try_parse_rgb(str); if (! success) { - bzero(this->data.rgb, sizeof this->data.rgb); + bzero(&this->data, sizeof this->data); this->type = type_none; } } @@ -351,7 +357,7 @@ wcstring rgb_color_t::description() const case type_named: return format_string(L"named(%d: %ls)", (int)data.name_idx, name_for_color_idx(data.name_idx)); case type_rgb: - return format_string(L"rgb(0x%02x%02x%02x)", data.rgb[0], data.rgb[1], data.rgb[2]); + return format_string(L"rgb(0x%02x%02x%02x)", data.color.rgb[0], data.color.rgb[1], data.color.rgb[2]); case type_reset: return L"reset"; case type_normal: diff --git a/color.h b/color.h index 6e22aaed5..db2fec712 100644 --- a/color.h +++ b/color.h @@ -8,6 +8,10 @@ #include "config.h" #include "common.h" +/* 24 bit color */ +struct color24_t { + unsigned char rgb[3]; +}; /* A type that represents a color. We work hard to keep it at a size of 4 bytes. */ class rgb_color_t @@ -36,7 +40,7 @@ class rgb_color_t union { unsigned char name_idx; //0-10 - unsigned char rgb[3]; + color24_t color; } data; /** Try parsing a special color name like "normal" */ @@ -129,9 +133,12 @@ public: /** Returns the name index for the given color. Requires that the color be named or RGB. */ unsigned char to_name_index() const; - /** Returns the term256 index for the given color. Requires that the color be named or RGB. */ + /** Returns the term256 index for the given color. Requires that the color be RGB. */ unsigned char to_term256_index() const; + /** Returns the 24 bit color for the given color. Requires that the color be RGB. */ + color24_t to_color24() const; + /** Returns whether the color is bold */ bool is_bold() const { diff --git a/env.cpp b/env.cpp index c9f986b10..6ae7f1772 100644 --- a/env.cpp +++ b/env.cpp @@ -325,7 +325,7 @@ static void react_to_variable_change(const wcstring &key) } else if (key == L"fish_term256") { - update_fish_term256(); + update_fish_color_support(); reader_react_to_color_change(); } else if (string_prefixes_string(L"fish_color_", key)) diff --git a/fish.cpp b/fish.cpp index 9f9b2ed2c..f5420e8aa 100644 --- a/fish.cpp +++ b/fish.cpp @@ -435,7 +435,7 @@ int main(int argc, char **argv) reader_init(); history_init(); /* For setcolor to support term256 in config.fish (#1022) */ - update_fish_term256(); + update_fish_color_support(); parser_t &parser = parser_t::principal_parser(); diff --git a/input.cpp b/input.cpp index 0d7a91be0..3b4c0ffaa 100644 --- a/input.cpp +++ b/input.cpp @@ -423,7 +423,7 @@ static int interrupt_handler() return R_NULL; } -void update_fish_term256(void) +void update_fish_color_support(void) { /* Infer term256 support. If fish_term256 is set, we respect it; otherwise try to detect it from the TERM variable */ env_var_t fish_term256 = env_get_string(L"fish_term256"); @@ -456,7 +456,20 @@ void update_fish_term256(void) support_term256 = false; } } - output_set_supports_term256(support_term256); + + env_var_t fish_term24bit = env_get_string(L"fish_term24bit"); + bool support_term24bit; + if (! fish_term24bit.missing_or_empty()) + { + support_term24bit = from_string(fish_term24bit); + } + else + { + support_term24bit = false; + } + + color_support_t support = (support_term256 ? color_support_term256 : 0) | (support_term24bit ? color_support_term24bit : 0); + output_set_color_support(support); } int input_init() @@ -496,7 +509,7 @@ int input_init() input_terminfo_init(); - update_fish_term256(); + update_fish_color_support(); /* If we have no keybindings, add a few simple defaults */ if (mapping_list.empty()) diff --git a/input.h b/input.h index 18d0d2b63..0f0b29084 100644 --- a/input.h +++ b/input.h @@ -185,8 +185,8 @@ wchar_t input_function_get_code(const wcstring &name); /** Returns a list of all existing input function names */ wcstring_list_t input_function_get_names(void); -/** Updates our idea of whether we support term256 */ -void update_fish_term256(); +/** Updates our idea of whether we support term256 and term24bit */ +void update_fish_color_support(); #endif diff --git a/output.cpp b/output.cpp index 149d9d99a..3a33ba7fa 100644 --- a/output.cpp +++ b/output.cpp @@ -107,8 +107,8 @@ static int (*out)(char c) = &writeb_internal; */ static wcstring current_term; -/* Whether term256 is supported */ -static bool support_term256 = false; +/* Whether term256 and term24bit are supported */ +static color_support_t color_support = 0; void output_set_writer(int (*writer)(char)) @@ -125,22 +125,22 @@ int (*output_get_writer())(char) static bool term256_support_is_native(void) { /* Return YES if we think the term256 support is "native" as opposed to forced. */ - return max_colors == 256; + return max_colors >= 256; } -bool output_get_supports_term256(void) +color_support_t output_get_color_support(void) { - return support_term256; + return color_support; } -void output_set_supports_term256(bool val) +void output_set_color_support(color_support_t val) { - support_term256 = val; + color_support = val; } unsigned char index_for_color(rgb_color_t c) { - if (c.is_named() || ! output_get_supports_term256()) + if (c.is_named() || ! (output_get_color_support() & color_support_term256)) { return c.to_name_index(); } @@ -686,7 +686,8 @@ rgb_color_t parse_color(const wcstring &val, bool is_background) // If we have both RGB and named colors, then prefer rgb if term256 is supported rgb_color_t result; - if ((!first_rgb.is_none() && output_get_supports_term256()) || first_named.is_none()) + bool has_term256 = !! (output_get_color_support() & color_support_term256); + if ((!first_rgb.is_none() && has_term256) || first_named.is_none()) { result = first_rgb; } diff --git a/output.h b/output.h index 400129421..9af26f731 100644 --- a/output.h +++ b/output.h @@ -134,9 +134,15 @@ void output_set_term(const wcstring &term); /** Return the terminal name */ const wchar_t *output_get_term(); -/** Sets whether term256 colors are supported */ -bool output_get_supports_term256(); -void output_set_supports_term256(bool val); +/** Sets what colors are supported */ +enum +{ + color_support_term256 = 1 << 0, + color_support_term24bit = 1 << 1 +}; +typedef unsigned int color_support_t; +color_support_t output_get_color_support(); +void output_set_color_support(color_support_t support); /* Exported for builtin_set_color's usage only */ bool write_foreground_color(unsigned char idx); diff --git a/screen.cpp b/screen.cpp index 9f1cc6e4d..0345ff707 100644 --- a/screen.cpp +++ b/screen.cpp @@ -1428,7 +1428,7 @@ void s_reset(screen_t *s, screen_reset_mode_t mode) int non_space_width = wcwidth(omitted_newline_char); if (screen_width >= non_space_width) { - if (output_get_supports_term256()) + if (output_get_color_support() & color_support_term256) { // draw the string in term256 gray abandon_line_string.append(L"\x1b[38;5;245m");