diff --git a/options-table.c b/options-table.c index 8e8b8b5d..8a611460 100644 --- a/options-table.c +++ b/options-table.c @@ -75,6 +75,11 @@ const struct options_table_entry server_options_table[] = { .default_num = 0 /* overridden in main() */ }, + { .name = "set-clipboard", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + { .name = NULL } }; @@ -360,7 +365,8 @@ const struct options_table_entry session_options_table[] = { { .name = "terminal-overrides", .type = OPTIONS_TABLE_STRING, - .default_str = "*88col*:colors=88,*256col*:colors=256,xterm*:XT" + .default_str = "*88col*:colors=88,*256col*:colors=256" + ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007" }, { .name = "update-environment", diff --git a/screen-write.c b/screen-write.c index 1fee190d..60623701 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1194,6 +1194,18 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width) } } +void +screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len) +{ + struct tty_ctx ttyctx; + + screen_write_initctx(ctx, &ttyctx, 0); + ttyctx.ptr = str; + ttyctx.num = len; + + tty_write(tty_cmd_setselection, &ttyctx); +} + void screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) { diff --git a/tmux.1 b/tmux.1 index 4b0083a0..c6a286a8 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1705,6 +1705,28 @@ Available server options are: Set the number of buffers; as new buffers are added to the top of the stack, old ones are removed from the bottom if necessary to maintain this maximum length. +.It Xo Ic set-clipboard +.Op Ic on | off +.Xc +Attempt to set the terminal clipboard content using the +\ee]52;...\e007 +.Xr xterm 1 +escape sequences. +This option is on by default if there is an +.Em \&Ms +entry in the +.Xr terminfo 5 +description for the client terminal. +Note that this feature needs to be enabled in +.Xr xterm 1 +by setting the resource: +.Bd -literal -offset indent +disallowedWindowOps: 20,21,SetXprop +.Ed +.Pp +Or changing this property from the +.Xr xterm 1 +interactive menu when required. .It Ic escape-time Ar time Set the time in milliseconds for which .Nm @@ -2796,6 +2818,21 @@ If the command doesn't return success, the exit status is also displayed. .D1 (alias: Ic info ) Show server information and terminal details. .El +.Sh TERMINFO EXTENSIONS +.Nm +understands some extensions to +.Xr terminfo 5 : +.Bl -tag -width Ds +.It Em \&Ms +This sequence can be used by +.Nm +to store the current buffer in the host terminal's selection (clipboard). +See the +.Em set-clipboard +option above and the +.Xr xterm 1 +man page. +.El .Sh FILES .Bl -tag -width "/etc/tmux.confXXX" -compact .It Pa ~/.tmux.conf diff --git a/tmux.h b/tmux.h index c7875df7..3056ac94 100644 --- a/tmux.h +++ b/tmux.h @@ -308,6 +308,7 @@ enum tty_code_code { TTYC_KUP5, TTYC_KUP6, TTYC_KUP7, + TTYC_MS, /* modify xterm(1) selection */ TTYC_OP, /* orig_pair, op */ TTYC_REV, /* enter_reverse_mode, mr */ TTYC_RI, /* scroll_reverse, sr */ @@ -1413,6 +1414,7 @@ void tty_cursor(struct tty *, u_int, u_int); void tty_putcode(struct tty *, enum tty_code_code); void tty_putcode1(struct tty *, enum tty_code_code, int); void tty_putcode2(struct tty *, enum tty_code_code, int, int); +void tty_putcode_ptr2(struct tty *, enum tty_code_code, const void *, const void *); void tty_puts(struct tty *, const char *); void tty_putc(struct tty *, u_char); void tty_pututf8(struct tty *, const struct grid_utf8 *); @@ -1444,6 +1446,7 @@ void tty_cmd_insertline(struct tty *, const struct tty_ctx *); void tty_cmd_linefeed(struct tty *, const struct tty_ctx *); void tty_cmd_utf8character(struct tty *, const struct tty_ctx *); void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *); +void tty_cmd_setselection(struct tty *, const struct tty_ctx *); void tty_cmd_rawstring(struct tty *, const struct tty_ctx *); /* tty-term.c */ @@ -1456,6 +1459,8 @@ const char *tty_term_string(struct tty_term *, enum tty_code_code); const char *tty_term_string1(struct tty_term *, enum tty_code_code, int); const char *tty_term_string2( struct tty_term *, enum tty_code_code, int, int); +const char *tty_term_ptr2( + struct tty_term *, enum tty_code_code, const void *, const void *); int tty_term_number(struct tty_term *, enum tty_code_code); int tty_term_flag(struct tty_term *, enum tty_code_code); @@ -1824,6 +1829,7 @@ void screen_write_clearstartofscreen(struct screen_write_ctx *); void screen_write_clearscreen(struct screen_write_ctx *); void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *, const struct utf8_data *); +void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); /* screen-redraw.c */ diff --git a/tty-term.c b/tty-term.c index f1e6d878..7ad4628f 100644 --- a/tty-term.c +++ b/tty-term.c @@ -163,6 +163,7 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = { { TTYC_KUP5, TTYCODE_STRING, "kUP5" }, { TTYC_KUP6, TTYCODE_STRING, "kUP6" }, { TTYC_KUP7, TTYCODE_STRING, "kUP7" }, + { TTYC_MS, TTYCODE_STRING, "Ms" }, { TTYC_OP, TTYCODE_STRING, "op" }, { TTYC_REV, TTYCODE_STRING, "rev" }, { TTYC_RI, TTYCODE_STRING, "ri" }, @@ -492,6 +493,12 @@ tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b) return (tparm((char *) tty_term_string(term, code), a, b)); } +const char * +tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b) +{ + return (tparm((char *) tty_term_string(term, code), a, b)); +} + int tty_term_number(struct tty_term *term, enum tty_code_code code) { diff --git a/tty.c b/tty.c index b423f6d8..04503b60 100644 --- a/tty.c +++ b/tty.c @@ -19,8 +19,11 @@ #include #include +#include + #include #include +#include #include #include #include @@ -311,6 +314,13 @@ tty_putcode2(struct tty *tty, enum tty_code_code code, int a, int b) tty_puts(tty, tty_term_string2(tty->term, code, a, b)); } +void +tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a, const void *b) +{ + if (a != NULL && b != NULL) + tty_puts(tty, tty_term_ptr2(tty->term, code, a, b)); +} + void tty_puts(struct tty *tty, const char *s) { @@ -938,6 +948,24 @@ tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx) tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff); } +void +tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx) +{ + char *buf; + size_t off; + + if (!tty_term_has(tty->term, TTYC_MS)) + return; + + off = 4 * ((ctx->num + 2) / 3) + 1; /* storage for base64 */ + buf = xmalloc(off); + + b64_ntop(ctx->ptr, ctx->num, buf, off); + tty_putcode_ptr2(tty, TTYC_MS, "", buf); + + xfree(buf); +} + void tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) { diff --git a/window-copy.c b/window-copy.c index 4ee3c3e3..1c060dc0 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1345,6 +1345,9 @@ window_copy_copy_selection(struct window_pane *wp) } off--; /* remove final \n */ + if (options_get_number(&global_options, "set-clipboard")) + screen_write_setselection(&wp->ictx.ctx, buf, off); + /* Add the buffer to the stack. */ limit = options_get_number(&global_options, "buffer-limit"); paste_add(&global_buffers, buf, off, limit);