support osc 52 clipboard copy integration.
This feature is particularly relevant for mosh for chrome (which also used in windows I believe).
This commit is contained in:
@@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
|
static const size_t MAXIMUM_CLIPBOARD_SIZE = 16*1024;
|
||||||
|
|
||||||
Dispatcher::Dispatcher()
|
Dispatcher::Dispatcher()
|
||||||
: params(), parsed_params(), parsed( false ), dispatch_chars(),
|
: params(), parsed_params(), parsed( false ), dispatch_chars(),
|
||||||
OSC_string(), terminal_to_host()
|
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 )
|
void Dispatcher::OSC_put( const Parser::OSC_Put *act )
|
||||||
{
|
{
|
||||||
assert( act->char_present );
|
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 );
|
OSC_string.push_back( act->ch );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() ) {
|
if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) {
|
||||||
frame.append( '\007' );
|
frame.append( '\007' );
|
||||||
}
|
}
|
||||||
|
typedef Terminal::Framebuffer::title_type title_type;
|
||||||
|
|
||||||
/* has icon name or window title changed? */
|
/* has icon name or window title changed? */
|
||||||
if ( has_title && f.is_title_initialized() &&
|
if ( has_title && f.is_title_initialized() &&
|
||||||
( (!initialized)
|
( (!initialized)
|
||||||
|| (f.get_icon_name() != frame.last_frame.get_icon_name())
|
|| (f.get_icon_name() != frame.last_frame.get_icon_name())
|
||||||
|| (f.get_window_title() != frame.last_frame.get_window_title()) ) ) {
|
|| (f.get_window_title() != frame.last_frame.get_window_title()) ) ) {
|
||||||
typedef Terminal::Framebuffer::title_type title_type;
|
|
||||||
/* set icon name and window title */
|
/* set icon name and window title */
|
||||||
if ( f.get_icon_name() == f.get_window_title() ) {
|
if ( f.get_icon_name() == f.get_window_title() ) {
|
||||||
/* write combined Icon Name and 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? */
|
/* has reverse video state changed? */
|
||||||
if ( (!initialized)
|
if ( (!initialized)
|
||||||
|| (f.ds.reverse_video != frame.last_frame.ds.reverse_video) ) {
|
|| (f.ds.reverse_video != frame.last_frame.ds.reverse_video) ) {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ DrawState::DrawState( int s_width, int s_height )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Framebuffer::Framebuffer( 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_height > 0 );
|
||||||
assert( s_width > 0 );
|
assert( s_width > 0 );
|
||||||
@@ -98,7 +98,8 @@ Framebuffer::Framebuffer( int s_width, int s_height )
|
|||||||
|
|
||||||
Framebuffer::Framebuffer( const Framebuffer &other )
|
Framebuffer::Framebuffer( const Framebuffer &other )
|
||||||
: rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ),
|
: 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;
|
rows = other.rows;
|
||||||
icon_name = other.icon_name;
|
icon_name = other.icon_name;
|
||||||
window_title = other.window_title;
|
window_title = other.window_title;
|
||||||
|
clipboard = other.clipboard;
|
||||||
bell_count = other.bell_count;
|
bell_count = other.bell_count;
|
||||||
title_initialized = other.title_initialized;
|
title_initialized = other.title_initialized;
|
||||||
ds = other.ds;
|
ds = other.ds;
|
||||||
@@ -397,6 +399,7 @@ void Framebuffer::reset( void )
|
|||||||
ds = DrawState( width, height );
|
ds = DrawState( width, height );
|
||||||
rows = rows_type( height, newrow() );
|
rows = rows_type( height, newrow() );
|
||||||
window_title.clear();
|
window_title.clear();
|
||||||
|
clipboard.clear();
|
||||||
/* do not reset bell_count */
|
/* do not reset bell_count */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ namespace Terminal {
|
|||||||
rows_type rows;
|
rows_type rows;
|
||||||
title_type icon_name;
|
title_type icon_name;
|
||||||
title_type window_title;
|
title_type window_title;
|
||||||
|
title_type clipboard;
|
||||||
unsigned int bell_count;
|
unsigned int bell_count;
|
||||||
bool title_initialized; /* true if the window title has been set via an OSC */
|
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; }
|
bool is_title_initialized( void ) const { return title_initialized; }
|
||||||
void set_icon_name( const title_type &s ) { icon_name = s; }
|
void set_icon_name( const title_type &s ) { icon_name = s; }
|
||||||
void set_window_title( const title_type &s ) { window_title = 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_icon_name( void ) const { return icon_name; }
|
||||||
const title_type & get_window_title( void ) const { return window_title; }
|
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 );
|
void prefix_window_title( const title_type &s );
|
||||||
|
|
||||||
@@ -452,7 +455,7 @@ namespace Terminal {
|
|||||||
|
|
||||||
bool operator==( const Framebuffer &x ) const
|
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 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
#include "parseraction.h"
|
#include "parseraction.h"
|
||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
/* Terminal functions -- routines activated by CSI, escape or a control char */
|
/* 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 */
|
/* xterm uses an Operating System Command to set the window title */
|
||||||
void Dispatcher::OSC_dispatch( const Parser::OSC_End *act __attribute((unused)), Framebuffer *fb )
|
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;
|
long cmd_num = -1;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if ( OSC_string[ 0 ] == L';' ) {
|
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);
|
bool set_title = (cmd_num == 0 || cmd_num == 2);
|
||||||
if ( set_icon || set_title ) {
|
if ( set_icon || set_title ) {
|
||||||
fb->set_title_initialized();
|
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_icon ) { fb->set_icon_name( newtitle ); }
|
||||||
if ( set_title ) { fb->set_window_title( newtitle ); }
|
if ( set_title ) { fb->set_window_title( newtitle ); }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user