From 57d97209c02f08bb2f58510a058e4556c449db18 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Fri, 16 Mar 2012 04:40:18 -0400 Subject: [PATCH] Support 256color (and assume 256color terminal). Closes #3 github issue. --- src/examples/termemu.cc | 2 +- src/frontend/mosh-server.cc | 2 +- src/terminal/terminalframebuffer.cc | 42 ++++++++++++++++++++++++++--- src/terminal/terminalframebuffer.h | 6 ++++- src/terminal/terminalfunctions.cc | 21 ++++++++++++--- 5 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/examples/termemu.cc b/src/examples/termemu.cc index bcc8756..fc2bb82 100644 --- a/src/examples/termemu.cc +++ b/src/examples/termemu.cc @@ -95,7 +95,7 @@ int main( void ) if ( child == 0 ) { /* child */ - if ( setenv( "TERM", "xterm", true ) < 0 ) { + if ( setenv( "TERM", "xterm-256color", true ) < 0 ) { perror( "setenv" ); exit( 1 ); } diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc index 5f72f47..0820c90 100644 --- a/src/frontend/mosh-server.cc +++ b/src/frontend/mosh-server.cc @@ -182,7 +182,7 @@ int run_server( const char *desired_ip, const char *desired_port ) { fatal_assert( sigprocmask( SIG_SETMASK, &signals_to_block, NULL ) == 0 ); /* set TERM */ - if ( setenv( "TERM", "xterm", true ) < 0 ) { + if ( setenv( "TERM", "xterm-256color", true ) < 0 ) { perror( "setenv" ); exit( 1 ); } diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index a9ed554..80dfbf0 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -369,6 +369,7 @@ Renditions::Renditions( int s_background ) background_color( s_background ) {} +/* This routine cannot be used to set a color beyond the 8-color set. */ void Renditions::set_rendition( int num ) { if ( num == 0 ) { @@ -377,10 +378,18 @@ void Renditions::set_rendition( int num ) return; } - if ( (30 <= num) && (num <= 39) ) { /* foreground color */ + if ( num == 39 ) { + foreground_color = 0; + return; + } else if ( num == 49 ) { + background_color = 0; + return; + } + + if ( (30 <= num) && (num <= 37) ) { /* foreground color in 8-color set */ foreground_color = num; return; - } else if ( (40 <= num) && (num <= 49) ) { /* background color */ + } else if ( (40 <= num) && (num <= 47) ) { /* background color in 8-color set */ background_color = num; return; } @@ -394,6 +403,20 @@ void Renditions::set_rendition( int num ) } } +void Renditions::set_foreground_color( int num ) +{ + if ( (0 <= num) && (num <= 255) ) { + foreground_color = 30 + num; + } +} + +void Renditions::set_background_color( int num ) +{ + if ( (0 <= num) && (num <= 255) ) { + background_color = 40 + num; + } +} + std::string Renditions::sgr( void ) const { std::string ret; @@ -404,16 +427,27 @@ std::string Renditions::sgr( void ) const if ( blink ) ret.append( ";5" ); if ( inverse ) ret.append( ";7" ); if ( invisible ) ret.append( ";8" ); - if ( foreground_color ) { + + if ( foreground_color > 37 ) { /* use 256-color set */ + char col[ 64 ]; + snprintf( col, 64, "m\033[38;5;%d", foreground_color - 30 ); + ret.append( col ); + } else if ( foreground_color ) { char col[ 8 ]; snprintf( col, 8, ";%d", foreground_color ); ret.append( col ); } - if ( background_color ) { + + if ( background_color > 47 ) { /* use 256-color set */ + char col[ 64 ]; + snprintf( col, 64, "m\033[48;5;%d", background_color - 40 ); + ret.append( col ); + } else if ( background_color ) { char col[ 8 ]; snprintf( col, 8, ";%d", background_color ); ret.append( col ); } + ret.append( "m" ); return ret; diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index da837a5..ae55612 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -35,6 +35,8 @@ namespace Terminal { int background_color; Renditions( int s_background ); + void set_foreground_color( int num ); + void set_background_color( int num ); void set_rendition( int num ); std::string sgr( void ) const; @@ -182,9 +184,11 @@ namespace Terminal { int limit_top( void ); int limit_bottom( void ); + void set_foreground_color( int x ) { renditions.set_foreground_color( x ); } + void set_background_color( int x ) { renditions.set_background_color( x ); } void add_rendition( int x ) { renditions.set_rendition( x ); } Renditions get_renditions( void ) const { return renditions; } - int get_background_rendition( void ) { return renditions.background_color; } + int get_background_rendition( void ) const { return renditions.background_color; } void save_cursor( void ); void restore_cursor( void ); diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index db5a368..90b8c0f 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -332,9 +332,24 @@ static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL ); /* select graphics rendition -- e.g., bold, blinking, etc. */ void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) { - for ( int i = 0; i < dispatch->param_count(); i++ ) { - int rendition = dispatch->getparam( i, 0 ); - fb->ds.add_rendition( rendition ); + /* We need to special-case the handling of CSI [34]8 ; 5 ; Ps m, + because Ps of 0 in that case does not mean reset to default, even + though it means that otherwise (as usually renditions are applied + in order). */ + + if ( (dispatch->param_count() == 3) + && (dispatch->getparam( 0, -1 ) == 38) + && (dispatch->getparam( 1, -1 ) == 5) ) { + fb->ds.set_foreground_color( dispatch->getparam( 2, 0 ) ); + } else if ( (dispatch->param_count() == 3) + && (dispatch->getparam( 0, -1 ) == 48) + && (dispatch->getparam( 1, -1 ) == 5) ) { + fb->ds.set_background_color( dispatch->getparam( 2, 0 ) ); + } else { + for ( int i = 0; i < dispatch->param_count(); i++ ) { + int rendition = dispatch->getparam( i, 0 ); + fb->ds.add_rendition( rendition ); + } } }