From 52d8fb301c5107c448936efda650044c5d27605a Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 13 Mar 2012 14:22:53 -0700 Subject: [PATCH] Added term256 support to set_color tool --- Makefile.in | 4 +- color.cpp | 10 ++- color.h | 4 + output.cpp | 212 -------------------------------------------------- output.h | 1 - set_color.cpp | 111 ++++++++++++++++++++------ 6 files changed, 101 insertions(+), 241 deletions(-) diff --git a/Makefile.in b/Makefile.in index dd17b008c..640e8c3c0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -753,8 +753,8 @@ mimedb: $(MIME_OBJS) # Build the set_color program # -set_color: set_color.o print_help.o common.o - $(CXX) set_color.o print_help.o common.o wutil.o $(LDFLAGS_SET_COLOR) -o $@ +set_color: set_color.o print_help.o common.o color.o + $(CXX) set_color.o print_help.o common.o wutil.o color.o $(LDFLAGS_SET_COLOR) -o $@ # diff --git a/color.cpp b/color.cpp index b6ffcb608..c739f3f3b 100644 --- a/color.cpp +++ b/color.cpp @@ -223,7 +223,7 @@ unsigned char rgb_color_t::to_name_index() const { } } -rgb_color_t::rgb_color_t(const wcstring &str) { +void rgb_color_t::parse(const wcstring &str) { bool success = false; if (! success) success = try_parse_special(str); if (! success) success = try_parse_named(str); @@ -245,6 +245,14 @@ rgb_color_t::rgb_color_t(const wcstring &str) { } } +rgb_color_t::rgb_color_t(const wcstring &str) { + this->parse(str); +} + +rgb_color_t::rgb_color_t(const std::string &str) { + this->parse(str2wcstring(str)); +} + wcstring rgb_color_t::description() const { switch (type) { case type_none: diff --git a/color.h b/color.h index 2e86a6753..23e5ba776 100644 --- a/color.h +++ b/color.h @@ -44,6 +44,9 @@ class rgb_color_t { /** Try parsing an explicit color name like "magenta" */ bool try_parse_named(const wcstring &str); + /* Parsing entry point */ + void parse(const wcstring &str); + /** Private constructor */ explicit rgb_color_t(unsigned char t, unsigned char i=0); @@ -54,6 +57,7 @@ class rgb_color_t { /** Parse a color from a string */ explicit rgb_color_t(const wcstring &str); + explicit rgb_color_t(const std::string &str); /** Returns white */ static rgb_color_t white(); diff --git a/output.cpp b/output.cpp index ea4eb3ef1..56e58f075 100644 --- a/output.cpp +++ b/output.cpp @@ -378,218 +378,6 @@ void set_color(rgb_color_t c, rgb_color_t c2) } -void set_color( int c, int c2 ) -{ - ASSERT_IS_MAIN_THREAD(); - - static int last_color = FISH_COLOR_NORMAL; - static int last_color2 = FISH_COLOR_NORMAL; - static int was_bold=0; - static int was_underline=0; - int bg_set=0, last_bg_set=0; - char *fg = 0, *bg=0; - - int is_bold = 0; - int is_underline = 0; - - /* - Test if we have at least basic support for setting fonts, colors - and related bits - otherwise just give up... - */ - if( !exit_attribute_mode ) - { - return; - } - - - is_bold |= (c&FISH_COLOR_BOLD)!=0; - is_bold |= (c2&FISH_COLOR_BOLD)!=0; - - is_underline |= (c&FISH_COLOR_UNDERLINE)!=0; - is_underline |= (c2&FISH_COLOR_UNDERLINE)!=0; - - c = c&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE)); - c2 = c2&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE)); - - if( (set_a_foreground != 0) && (strlen( set_a_foreground) != 0 ) ) - { - fg = set_a_foreground; - bg = set_a_background; - } - else if( (set_foreground != 0) && (strlen( set_foreground) != 0 ) ) - { - fg = set_foreground; - bg = set_background; - } - - if( (c == FISH_COLOR_RESET) || (c2 == FISH_COLOR_RESET)) - { - c = c2 = FISH_COLOR_NORMAL; - was_bold=0; - was_underline=0; - if( fg ) - { - /* - If we exit attibute mode, we must first set a color, or - previously coloured text might lose it's - color. Terminals are weird... - */ - writembs( tparm( fg, 0 ) ); - } - writembs( exit_attribute_mode ); - return; - } - - if( was_bold && !is_bold ) - { - /* - Only way to exit bold mode is a reset of all attributes. - */ - writembs( exit_attribute_mode ); - last_color = FISH_COLOR_NORMAL; - last_color2 = FISH_COLOR_NORMAL; - was_bold=0; - was_underline=0; - } - - if( last_color2 != FISH_COLOR_NORMAL && - last_color2 != FISH_COLOR_RESET && - last_color2 != FISH_COLOR_IGNORE ) - { - /* - Background was set - */ - last_bg_set=1; - } - - if( c2 != FISH_COLOR_NORMAL && - c2 != FISH_COLOR_IGNORE ) - { - /* - Background is set - */ - bg_set=1; - c = (c2==FISH_COLOR_WHITE)?FISH_COLOR_BLACK:FISH_COLOR_WHITE; - } - - if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0)) - { - if(bg_set && !last_bg_set) - { - /* - Background color changed and is set, so we enter bold - mode to make reading easier. This means bold mode is - _always_ on when the background color is set. - */ - writembs( enter_bold_mode ); - } - if(!bg_set && last_bg_set) - { - /* - Background color changed and is no longer set, so we - exit bold mode - */ - writembs( exit_attribute_mode ); - was_bold=0; - was_underline=0; - /* - We don't know if exit_attribute_mode resets colors, so - we set it to something known. - */ - if( fg ) - { - writembs( tparm( fg, 0 ) ); - last_color=0; - } - } - } - - if( last_color != c ) - { - if( c==FISH_COLOR_NORMAL ) - { - if( fg ) - { - writembs( tparm( fg, 0 ) ); - } - writembs( exit_attribute_mode ); - - last_color2 = FISH_COLOR_NORMAL; - was_bold=0; - was_underline=0; - } - else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) ) - { - if( fg ) - { - writembs( tparm( fg, c ) ); - } - } - } - - last_color = c; - - if( last_color2 != c2 ) - { - if( c2 == FISH_COLOR_NORMAL ) - { - if( bg ) - { - writembs( tparm( bg, 0 ) ); - } - - writembs( exit_attribute_mode ); - if( ( last_color != FISH_COLOR_NORMAL ) && fg ) - { - if( fg ) - { - writembs( tparm( fg, last_color ) ); - } - } - - - was_bold=0; - was_underline=0; - last_color2 = c2; - } - else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) ) - { - if( bg ) - { - writembs( tparm( bg, c2 ) ); - } - last_color2 = c2; - } - } - - /* - Lastly, we set bold mode and underline mode correctly - */ - if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set ) - { - if( is_bold && !was_bold ) - { - if( enter_bold_mode ) - { - writembs( tparm( enter_bold_mode ) ); - } - } - was_bold = is_bold; - } - - if( was_underline && !is_underline ) - { - writembs( exit_underline_mode ); - } - - if( !was_underline && is_underline ) - { - writembs( enter_underline_mode ); - } - was_underline = is_underline; - -} - /** Default output method, simply calls write() on stdout */ diff --git a/output.h b/output.h index 30fb23251..0bc432b81 100644 --- a/output.h +++ b/output.h @@ -73,7 +73,6 @@ enum */ -//void set_color( int c, int c2 ); void set_color(rgb_color_t c, rgb_color_t c2); /** diff --git a/set_color.cpp b/set_color.cpp index 181ad9ab2..7366ba814 100644 --- a/set_color.cpp +++ b/set_color.cpp @@ -38,6 +38,7 @@ #include "fallback.h" #include "print_help.h" +#include "color.h" /* Small utility for setting the color. @@ -143,14 +144,73 @@ static void check_locale_init() textdomain( PACKAGE_NAME ); } +/* A lot of this code is taken straight from output.cpp; it sure would be nice to factor these together. */ + +static bool support_term256; +static bool output_get_supports_term256(void) { + return support_term256; +} + +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; +} + +static bool write_color(char *todo, unsigned char idx, bool is_fg) { + bool result = false; + if (idx < 16 || term256_support_is_native()) { + /* Use tparm */ + putp( tparm( todo, idx ) ); + result = true; + } else { + /* We are attempting to bypass the term here. Generate the ANSI escape sequence ourself. */ + char stridx[128]; + format_long_safe(stridx, (long)idx); + char buff[128] = "\x1b["; + strcat(buff, is_fg ? "38;5;" : "48;5;"); + strcat(buff, stridx); + strcat(buff, "m"); + write_loop(STDOUT_FILENO, buff, strlen(buff)); + result = true; + } + return result; +} + +static bool write_foreground_color(unsigned char idx) { + if (set_a_foreground && set_a_foreground[0]) { + return write_color(set_a_foreground, idx, true); + } else if (set_foreground && set_foreground[0]) { + return write_color(set_foreground, idx, true); + } else { + return false; + } +} + +static bool write_background_color(unsigned char idx) { + if (set_a_background && set_a_background[0]) { + return write_color(set_a_background, idx, false); + } else if (set_background && set_background[0]) { + return write_color(set_background, idx, false); + } else { + return false; + } +} + +static unsigned char index_for_color(rgb_color_t c) { + if (c.is_named() || ! output_get_supports_term256()) { + return c.to_name_index(); + } else { + return c.to_term256_index(); + } +} + int main( int argc, char **argv ) { char *bgcolor=0; char *fgcolor=0; - int fg, bg; - int bold=0; - int underline=0; + bool bold=false; + bool underline=false; char *bg_seq, *fg_seq; while( 1 ) @@ -212,11 +272,11 @@ int main( int argc, char **argv ) exit(0); case 'o': - bold=1; + bold=true; break; case 'u': - underline=1; + underline=true; break; case 'v': @@ -251,6 +311,15 @@ int main( int argc, char **argv ) printf( _("%s: Too many arguments\n"), SET_COLOR ); return 1; } + + /* Infer term256 support */ + char *fish_term256 = getenv("fish_term256"); + if (fish_term256) { + support_term256 = from_string(fish_term256); + } else { + const char *term = getenv("TERM"); + support_term256 = term && strstr(term, "256color"); + } if( !fgcolor && !bgcolor && !bold && !underline ) { @@ -259,17 +328,17 @@ int main( int argc, char **argv ) print_help( argv[0], 2 ); return 1; } - - fg = translate_color(fgcolor); - if( fgcolor && (fg==-1)) + + rgb_color_t fg = rgb_color_t(fgcolor ? fgcolor : ""); + if( fgcolor && fg.is_none()) { check_locale_init(); fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, fgcolor ); return 1; } - bg = translate_color(bgcolor); - if( bgcolor && (bg==-1)) + rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : ""); + if( bgcolor && bg.is_none()) { check_locale_init(); fprintf( stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, bgcolor ); @@ -278,10 +347,6 @@ int main( int argc, char **argv ) setupterm( 0, STDOUT_FILENO, 0); - fg_seq = set_a_foreground?set_a_foreground:set_foreground; - bg_seq = set_a_background?set_a_background:set_background; - - if( bold ) { if( enter_bold_mode ) @@ -296,35 +361,31 @@ int main( int argc, char **argv ) if( bgcolor ) { - if( bg == 8 ) + if( bg.is_normal() ) { - if( bg_seq ) - putp( tparm( bg_seq, 0) ); + write_background_color(0); putp( tparm(exit_attribute_mode) ); } } if( fgcolor ) { - if( fg == 8 ) + if( fg.is_normal() ) { - if( fg_seq ) - putp( tparm( fg_seq, 0) ); + write_foreground_color(0); putp( tparm(exit_attribute_mode) ); } else { - if( fg_seq ) - putp( tparm( fg_seq, fg) ); + write_foreground_color(index_for_color(fg)); } } if( bgcolor ) { - if( bg != 8 ) + if( ! bg.is_normal() ) { - if( bg_seq ) - putp( tparm( bg_seq, bg) ); + write_background_color(index_for_color(bg)); } }