diff --git a/src/frontend/terminaloverlay.cc b/src/frontend/terminaloverlay.cc index 26d81cb..27eef05 100644 --- a/src/frontend/terminaloverlay.cc +++ b/src/frontend/terminaloverlay.cc @@ -206,8 +206,8 @@ void NotificationEngine::apply( Framebuffer &fb ) const /* draw bar across top of screen */ Cell notification_bar( 0 ); - notification_bar.get_renditions().foreground_color = 37; - notification_bar.get_renditions().background_color = 44; + notification_bar.get_renditions().set_foreground_color( 7 ); + notification_bar.get_renditions().set_background_color( 4 ); notification_bar.append( 0x20 ); for ( int i = 0; i < fb.ds.get_width(); i++ ) { @@ -276,8 +276,8 @@ void NotificationEngine::apply( Framebuffer &fb ) const this_cell = fb.get_mutable_cell( 0, overlay_col ); fb.reset_cell( this_cell ); this_cell->get_renditions().set_attribute(Renditions::bold, true); - this_cell->get_renditions().foreground_color = 37; - this_cell->get_renditions().background_color = 44; + this_cell->get_renditions().set_foreground_color( 7 ); + this_cell->get_renditions().set_background_color( 4 ); this_cell->append( ch ); this_cell->set_wide( chwidth == 2 ); diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index a4b90ea..a15faee 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -517,6 +517,8 @@ void Renditions::set_foreground_color( int num ) { if ( (0 <= num) && (num <= 255) ) { foreground_color = 30 + num; + } else if ( is_true_color( num ) ) { + foreground_color = num; } } @@ -524,12 +526,15 @@ void Renditions::set_background_color( int num ) { if ( (0 <= num) && (num <= 255) ) { background_color = 40 + num; + } else if ( is_true_color( num ) ) { + background_color = num; } } std::string Renditions::sgr( void ) const { std::string ret; + char col[64]; ret.append( "\033[0" ); if ( get_attribute( bold ) ) ret.append( ";1" ); @@ -539,35 +544,34 @@ std::string Renditions::sgr( void ) const if ( get_attribute( inverse ) ) ret.append( ";7" ); if ( get_attribute( invisible ) ) ret.append( ";8" ); - if ( foreground_color - && (foreground_color <= 37) ) { - /* ANSI foreground color */ - char col[ 8 ]; - snprintf( col, 8, ";%d", foreground_color ); + if ( foreground_color ) { + if ( is_true_color( foreground_color ) ) { + snprintf( col, sizeof( col ), ";38;2;%u;%u;%u", + (foreground_color >> 16) & 0xff, + (foreground_color >> 8) & 0xff, + foreground_color & 0xff); + } else if ( foreground_color > 37 ) { /* use 256-color set */ + snprintf( col, sizeof( col ), ";38;5;%u", foreground_color - 30 ); + } else { /* ANSI foreground color */ + snprintf( col, sizeof( col ), ";%u", static_cast( foreground_color ) ); + } ret.append( col ); } - - if ( background_color - && (background_color <= 47) ) { - char col[ 8 ]; - snprintf( col, 8, ";%d", background_color ); + if ( background_color ) { + if ( is_true_color( background_color ) ) { + snprintf( col, sizeof( col ), ";48;2;%u;%u;%u", + (background_color >> 16) & 0xff, + (background_color >> 8) & 0xff, + background_color & 0xff); + } else if ( background_color > 47 ) { /* use 256-color set */ + snprintf( col, sizeof( col ), ";48;5;%u", background_color - 40 ); + } else { /* ANSI background color */ + snprintf( col, sizeof( col ), ";%u", static_cast( background_color ) ); + } ret.append( col ); } - ret.append( "m" ); - if ( foreground_color > 37 ) { /* use 256-color set */ - char col[ 64 ]; - snprintf( col, 64, "\033[38;5;%dm", foreground_color - 30 ); - ret.append( col ); - } - - if ( background_color > 47 ) { /* use 256-color set */ - char col[ 64 ]; - snprintf( col, 64, "\033[48;5;%dm", background_color - 40 ); - ret.append( col ); - } - return ret; } diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index ca669ab..0e69bda 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -49,17 +49,17 @@ namespace Terminal { using shared::shared_ptr; using shared::make_shared; - typedef uint16_t color_type; + typedef uint32_t color_type; class Renditions { public: typedef enum { bold, faint, italic, underlined, blink, inverse, invisible, SIZE } attribute_type; - // all together, a 32 bit word now... - unsigned int foreground_color : 12; - unsigned int background_color : 12; private: - unsigned int attributes : 8; + static const uint64_t true_color_mask = 0x1000000; + uint64_t foreground_color : 25; + uint64_t background_color : 25; + uint64_t attributes : 8; public: Renditions( color_type s_background ); @@ -68,6 +68,17 @@ namespace Terminal { void set_rendition( color_type num ); std::string sgr( void ) const; + static unsigned int make_true_color( unsigned int r, unsigned int g, unsigned int b ) { + return true_color_mask | (r << 16) | (g << 8) | b; + } + + static bool is_true_color(unsigned int color) { + return (color & true_color_mask) != 0; + } + + // unsigned int get_foreground_rendition() const { return foreground_color; } + unsigned int get_background_rendition() const { return background_color; } + bool operator==( const Renditions &x ) const { return ( attributes == x.attributes ) @@ -321,7 +332,7 @@ namespace Terminal { void add_rendition( color_type x ) { renditions.set_rendition( x ); } const Renditions& get_renditions( void ) const { return renditions; } Renditions& get_renditions( void ) { return renditions; } - int get_background_rendition( void ) const { return renditions.background_color; } + int get_background_rendition( void ) const { return renditions.get_background_rendition(); } void save_cursor( void ); void restore_cursor( void ); diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index 22bf4f0..126986d 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -414,6 +414,27 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) i += 2; continue; } + + /* True color support: ESC[ ... [34]8;2;;; ... m */ + if ( (rendition == 38 || rendition == 48) && + (dispatch->param_count() - i >= 5) && + (dispatch->getparam( i+1, -1 ) == 2)) { + unsigned int red = dispatch->getparam(i+2, 0); + unsigned int green = dispatch->getparam(i+3, 0); + unsigned int blue = dispatch->getparam(i+4, 0); + unsigned int color; + + color = Renditions::make_true_color( red, green, blue ); + + if ( rendition == 38 ) { + fb->ds.set_foreground_color( color ); + } else { + fb->ds.set_background_color( color ); + } + i += 4; + continue; + } + fb->ds.add_rendition( rendition ); } }