aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Kang.Jianbin <kjbmail@gmail.com>2017-10-27 02:47:24 +0800
committerGravatar John Hood <cgull@glup.org>2017-10-29 20:20:03 -0400
commit6cfa4aef598146cfbde7f7a4a83438c3769a2835 (patch)
tree887dee60d26b9f5c37641988daf90a6bc3f284b9
parent70d1ca444f25b9e1d062d34ca73bfbd6c5e67f73 (diff)
Add true color support.
Implement true color support define in: https://en.wikipedia.org/wiki/ANSI_escape_code The sequence is: ESC[ … 38;2;;; … m Select RGB foreground color ESC[ … 48;2;;; … m Select RGB background color
-rw-r--r--src/terminal/terminalframebuffer.cc22
-rw-r--r--src/terminal/terminalframebuffer.h14
-rw-r--r--src/terminal/terminalfunctions.cc21
3 files changed, 52 insertions, 5 deletions
diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc
index 222f533..84b06cb 100644
--- a/src/terminal/terminalframebuffer.cc
+++ b/src/terminal/terminalframebuffer.cc
@@ -505,6 +505,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;
}
}
@@ -512,6 +514,8 @@ 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;
}
}
@@ -544,13 +548,27 @@ std::string Renditions::sgr( void ) const
ret.append( "m" );
- if ( foreground_color > 37 ) { /* use 256-color set */
+ if ( is_true_color( foreground_color ) ) {
+ char col[64];
+ snprintf( col, 64, "\033[38;2;%d;%d;%dm",
+ (foreground_color >> 16) & 0xff,
+ (foreground_color >> 8) & 0xff,
+ foreground_color & 0xff);
+ ret.append( col );
+ } else 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 */
+ if ( is_true_color( background_color ) ) {
+ char col[64];
+ snprintf( col, 64, "\033[48;2;%d;%d;%dm",
+ (background_color >> 16) & 0xff,
+ (background_color >> 8) & 0xff,
+ background_color & 0xff);
+ ret.append( col );
+ } else if ( background_color > 47 ) { /* use 256-color set */
char col[ 64 ];
snprintf( col, 64, "\033[48;5;%dm", background_color - 40 );
ret.append( col );
diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h
index f159aea..723dc0a 100644
--- a/src/terminal/terminalframebuffer.h
+++ b/src/terminal/terminalframebuffer.h
@@ -55,9 +55,9 @@ namespace Terminal {
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;
+ static const unsigned int true_color_mask = 0x80000000;
+ unsigned int foreground_color;
+ unsigned int background_color;
private:
unsigned int attributes : 8;
@@ -68,6 +68,14 @@ 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;
+ }
+
bool operator==( const Renditions &x ) const
{
return ( attributes == x.attributes )
diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc
index a0210e3..c53a4fa 100644
--- a/src/terminal/terminalfunctions.cc
+++ b/src/terminal/terminalfunctions.cc
@@ -424,6 +424,27 @@ static void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch )
i += 2;
continue;
}
+
+ /* True color support: ESC[ ... [34]8;2;<r>;<g>;<b> ... 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 );
}
}