diff --git a/src/terminal/terminaldispatcher.cc b/src/terminal/terminaldispatcher.cc index b7c0ee9..1e31491 100644 --- a/src/terminal/terminaldispatcher.cc +++ b/src/terminal/terminaldispatcher.cc @@ -42,6 +42,8 @@ using namespace Terminal; +static const size_t MAXIMUM_CLIPBOARD_SIZE = 16*1024; + Dispatcher::Dispatcher() : params(), parsed_params(), parsed( false ), dispatch_chars(), OSC_string(), terminal_to_host() @@ -235,7 +237,7 @@ void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, Frameb void Dispatcher::OSC_put( const Parser::OSC_Put *act ) { assert( act->char_present ); - if ( OSC_string.size() < 256 ) { /* should be a long enough window title */ + if ( OSC_string.size() < MAXIMUM_CLIPBOARD_SIZE) { OSC_string.push_back( act->ch ); } } diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index 74d662e..d7081b6 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -68,13 +68,13 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) { frame.append( '\007' ); } + typedef Terminal::Framebuffer::title_type title_type; /* has icon name or window title changed? */ if ( has_title && f.is_title_initialized() && ( (!initialized) || (f.get_icon_name() != frame.last_frame.get_icon_name()) || (f.get_window_title() != frame.last_frame.get_window_title()) ) ) { - typedef Terminal::Framebuffer::title_type title_type; /* set icon name and window title */ if ( f.get_icon_name() == f.get_window_title() ) { /* write combined Icon Name and Window Title */ @@ -110,6 +110,18 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const } + /* has clipboard changed? */ + if (f.get_clipboard() != frame.last_frame.get_clipboard()) { + frame.append( "\033]52;c;" ); + const title_type &clipboard( f.get_clipboard() ); + for ( title_type::const_iterator i = clipboard.begin(); + i != clipboard.end(); + i++ ) { + frame.append( *i ); + } + frame.append( '\007' ); + } + /* has reverse video state changed? */ if ( (!initialized) || (f.ds.reverse_video != frame.last_frame.ds.reverse_video) ) { diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index a4b90ea..316e299 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -87,7 +87,7 @@ DrawState::DrawState( int s_width, int s_height ) } Framebuffer::Framebuffer( int s_width, int s_height ) - : rows(), icon_name(), window_title(), bell_count( 0 ), title_initialized( false ), ds( s_width, s_height ) + : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ), ds( s_width, s_height ) { assert( s_height > 0 ); assert( s_width > 0 ); @@ -98,7 +98,8 @@ Framebuffer::Framebuffer( int s_width, int s_height ) Framebuffer::Framebuffer( const Framebuffer &other ) : rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ), - bell_count( other.bell_count ), title_initialized( other.title_initialized ), ds( other.ds ) + clipboard( other.clipboard ), bell_count( other.bell_count ), + title_initialized( other.title_initialized ), ds( other.ds ) { } @@ -108,6 +109,7 @@ Framebuffer & Framebuffer::operator=( const Framebuffer &other ) rows = other.rows; icon_name = other.icon_name; window_title = other.window_title; + clipboard = other.clipboard; bell_count = other.bell_count; title_initialized = other.title_initialized; ds = other.ds; @@ -397,6 +399,7 @@ void Framebuffer::reset( void ) ds = DrawState( width, height ); rows = rows_type( height, newrow() ); window_title.clear(); + clipboard.clear(); /* do not reset bell_count */ } diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index ca669ab..fa72bf5 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -365,6 +365,7 @@ namespace Terminal { rows_type rows; title_type icon_name; title_type window_title; + title_type clipboard; unsigned int bell_count; bool title_initialized; /* true if the window title has been set via an OSC */ @@ -437,8 +438,10 @@ namespace Terminal { bool is_title_initialized( void ) const { return title_initialized; } void set_icon_name( const title_type &s ) { icon_name = s; } void set_window_title( const title_type &s ) { window_title = s; } + void set_clipboard( const title_type &s ) { clipboard = s; } const title_type & get_icon_name( void ) const { return icon_name; } const title_type & get_window_title( void ) const { return window_title; } + const title_type & get_clipboard( void ) const { return clipboard; } void prefix_window_title( const title_type &s ); @@ -452,7 +455,7 @@ namespace Terminal { bool operator==( const Framebuffer &x ) const { - return ( rows == x.rows ) && ( window_title == x.window_title ) && ( bell_count == x.bell_count ) && ( ds == x.ds ); + return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) && ( bell_count == x.bell_count ) && ( ds == x.ds ); } }; } diff --git a/src/terminal/terminalfunctions.cc b/src/terminal/terminalfunctions.cc index 22bf4f0..a25f927 100644 --- a/src/terminal/terminalfunctions.cc +++ b/src/terminal/terminalfunctions.cc @@ -31,6 +31,7 @@ */ #include +#include #include #include @@ -39,6 +40,7 @@ #include "parseraction.h" using namespace Terminal; +using namespace std; /* Terminal functions -- routines activated by CSI, escape or a control char */ @@ -559,7 +561,15 @@ static Function func_CSI_DECSTR( CSI, "!p", CSI_DECSTR ); /* xterm uses an Operating System Command to set the window title */ void Dispatcher::OSC_dispatch( const Parser::OSC_End *act __attribute((unused)), Framebuffer *fb ) { - if ( OSC_string.size() >= 1 ) { + /* handle osc copy clipboard sequence 52;c; */ + if ( OSC_string.size() >= 5 && OSC_string[ 0 ] == L'5' && + OSC_string[ 1 ] == L'2' && OSC_string[ 2 ] == L';' && + OSC_string[ 3 ] == L'c' && OSC_string[ 4 ] == L';') { + Terminal::Framebuffer::title_type clipboard( + OSC_string.begin() + 5, OSC_string.end() ); + fb->set_clipboard( clipboard ); + /* handle osc terminal title sequence */ + } else if ( OSC_string.size() >= 1 ) { long cmd_num = -1; int offset = 0; if ( OSC_string[ 0 ] == L';' ) { @@ -578,7 +588,8 @@ void Dispatcher::OSC_dispatch( const Parser::OSC_End *act __attribute((unused)), bool set_title = (cmd_num == 0 || cmd_num == 2); if ( set_icon || set_title ) { fb->set_title_initialized(); - Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.end() ); + int title_length = min(OSC_string.size(), (size_t)256); + Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.begin() + title_length ); if ( set_icon ) { fb->set_icon_name( newtitle ); } if ( set_title ) { fb->set_window_title( newtitle ); } }