Skip to content

Commit

Permalink
support osc 52 clipboard copy integration.
Browse files Browse the repository at this point in the history
This feature is particularly relevant for mosh for chrome (which also
used in windows I believe).
  • Loading branch information
acornejo authored and cgull committed Aug 1, 2017
1 parent 04f6daf commit 4b240ac
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 7 deletions.
4 changes: 3 additions & 1 deletion src/terminal/terminaldispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 );
}
}
Expand Down
14 changes: 13 additions & 1 deletion src/terminal/terminaldisplay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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) ) {
Expand Down
7 changes: 5 additions & 2 deletions src/terminal/terminalframebuffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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 )
{
}

Expand All @@ -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;
Expand Down Expand Up @@ -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 */
}

Expand Down
5 changes: 4 additions & 1 deletion src/terminal/terminalframebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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 );

Expand All @@ -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 );
}
};
}
Expand Down
15 changes: 13 additions & 2 deletions src/terminal/terminalfunctions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
*/

#include <unistd.h>
#include <algorithm>
#include <string>
#include <stdio.h>

Expand All @@ -39,6 +40,7 @@
#include "parseraction.h"

using namespace Terminal;
using namespace std;

/* Terminal functions -- routines activated by CSI, escape or a control char */

Expand Down Expand Up @@ -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';' ) {
Expand All @@ -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 ); }
}
Expand Down

0 comments on commit 4b240ac

Please sign in to comment.