diff --git a/builtin_set_color.cpp b/builtin_set_color.cpp index 79a81bbb9..1cce8097b 100644 --- a/builtin_set_color.cpp +++ b/builtin_set_color.cpp @@ -211,7 +211,7 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv) { if (bg.is_normal()) { - write_background_color(0); + write_color(rgb_color_t::black(), false /* not is_fg */); writembs(tparm(exit_attribute_mode)); } } @@ -220,12 +220,12 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv) { if (fg.is_normal() || fg.is_reset()) { - write_foreground_color(0); + write_color(rgb_color_t::black(), true /* is_fg */); writembs(tparm(exit_attribute_mode)); } else { - write_foreground_color(index_for_color(fg)); + write_color(fg, true /* is_fg */); } } @@ -233,7 +233,7 @@ static int builtin_set_color(parser_t &parser, wchar_t **argv) { if (! bg.is_normal() && ! bg.is_reset()) { - write_background_color(index_for_color(bg)); + write_color(bg, false /* not is_fg */); } } diff --git a/color.h b/color.h index db2fec712..b3da47d02 100644 --- a/color.h +++ b/color.h @@ -9,7 +9,8 @@ #include "common.h" /* 24 bit color */ -struct color24_t { +struct color24_t +{ unsigned char rgb[3]; }; diff --git a/env.cpp b/env.cpp index 6ae7f1772..2fe3767bb 100644 --- a/env.cpp +++ b/env.cpp @@ -323,7 +323,7 @@ static void react_to_variable_change(const wcstring &key) { handle_locale(); } - else if (key == L"fish_term256") + else if (key == L"fish_term256" || key == L"fish_term24bit") { update_fish_color_support(); reader_react_to_color_change(); diff --git a/input.cpp b/input.cpp index 3b4c0ffaa..6811d0eba 100644 --- a/input.cpp +++ b/input.cpp @@ -465,6 +465,7 @@ void update_fish_color_support(void) } else { + /* We don't attempt to infer term24 bit support yet. */ support_term24bit = false; } diff --git a/output.cpp b/output.cpp index 3a33ba7fa..312a90777 100644 --- a/output.cpp +++ b/output.cpp @@ -151,7 +151,7 @@ unsigned char index_for_color(rgb_color_t c) } -static bool write_color(char *todo, unsigned char idx, bool is_fg) +static bool write_color_escape(char *todo, unsigned char idx, bool is_fg) { bool result = false; if (idx < 16 || term256_support_is_native()) @@ -184,15 +184,15 @@ static bool write_color(char *todo, unsigned char idx, bool is_fg) return result; } -bool write_foreground_color(unsigned char idx) +static bool write_foreground_color(unsigned char idx) { if (set_a_foreground && set_a_foreground[0]) { - return write_color(set_a_foreground, idx, true); + return write_color_escape(set_a_foreground, idx, true); } else if (set_foreground && set_foreground[0]) { - return write_color(set_foreground, idx, true); + return write_color_escape(set_foreground, idx, true); } else { @@ -200,15 +200,15 @@ bool write_foreground_color(unsigned char idx) } } -bool write_background_color(unsigned char idx) +static bool write_background_color(unsigned char idx) { if (set_a_background && set_a_background[0]) { - return write_color(set_a_background, idx, false); + return write_color_escape(set_a_background, idx, false); } else if (set_background && set_background[0]) { - return write_color(set_background, idx, false); + return write_color_escape(set_background, idx, false); } else { @@ -216,6 +216,34 @@ bool write_background_color(unsigned char idx) } } +void write_color(rgb_color_t color, bool is_fg) +{ + bool supports_term24bit = !! (output_get_color_support() & color_support_term24bit); + if (! supports_term24bit || ! color.is_rgb()) + { + /* Indexed or non-24 bit color */ + unsigned char idx = index_for_color(color); + (is_fg ? write_foreground_color : write_background_color)(idx); + } + else + { + /* 24 bit! No tparm here, just ANSI escape sequences. + Foreground: ^[38;2;;;m + Background: ^[48;2;;;m + */ + color24_t rgb = color.to_color24(); + char buff[128]; + snprintf(buff, sizeof buff, "\x1b[%u;2;%u;%u;%um", is_fg ? 38 : 48, rgb.rgb[0], rgb.rgb[1], rgb.rgb[2]); + int (*writer)(char) = output_get_writer(); + if (writer) + { + for (size_t i=0; buff[i]; i++) + { + writer(buff[i]); + } + } + } +} void set_color(rgb_color_t c, rgb_color_t c2) { @@ -345,7 +373,7 @@ void set_color(rgb_color_t c, rgb_color_t c2) } else if (! c.is_special()) { - write_foreground_color(index_for_color(c)); + write_color(c, true /* foreground */); } } @@ -360,7 +388,7 @@ void set_color(rgb_color_t c, rgb_color_t c2) writembs(exit_attribute_mode); if (! last_color.is_normal()) { - write_foreground_color(index_for_color(last_color)); + write_color(last_color, true /* foreground */); } @@ -370,7 +398,7 @@ void set_color(rgb_color_t c, rgb_color_t c2) } else if (! c2.is_special()) { - write_background_color(index_for_color(c2)); + write_color(c2, false /* not foreground */); last_color2 = c2; } } diff --git a/output.h b/output.h index 9af26f731..f0badf8a5 100644 --- a/output.h +++ b/output.h @@ -145,8 +145,7 @@ 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); -bool write_background_color(unsigned char idx); +void write_color(rgb_color_t color, bool is_fg); unsigned char index_for_color(rgb_color_t c); #endif