diff --git a/input.c b/input.c index 45b70db6..c8ae3544 100644 --- a/input.c +++ b/input.c @@ -101,6 +101,7 @@ struct input_ctx { struct bufferevent *event; struct screen_write_ctx ctx; struct colour_palette *palette; + struct client *c; struct input_cell cell; struct input_cell old_cell; @@ -854,7 +855,7 @@ input_restore_state(struct input_ctx *ictx) /* Initialise input parser. */ struct input_ctx * input_init(struct window_pane *wp, struct bufferevent *bev, - struct colour_palette *palette) + struct colour_palette *palette, struct client *c) { struct input_ctx *ictx; @@ -862,6 +863,7 @@ input_init(struct window_pane *wp, struct bufferevent *bev, ictx->wp = wp; ictx->event = bev; ictx->palette = palette; + ictx->c = c; ictx->input_space = INPUT_BUF_START; ictx->input_buf = xmalloc(INPUT_BUF_START); @@ -3073,31 +3075,28 @@ input_osc_52_reply(struct input_ctx *ictx) input_add_request(ictx, INPUT_REQUEST_CLIPBOARD, ictx->input_end); } -/* Handle the OSC 52 sequence for setting the clipboard. */ -static void -input_osc_52(struct input_ctx *ictx, const char *p) +/* + * Parse and decode OSC 52 clipboard data. Returns 0 on failure or if handled + * as a query. On success, returns 1 and sets *out, *outlen, and *flags (caller + * must free *out). + */ +static int +input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out, + int *outlen, char *flags) { - struct window_pane *wp = ictx->wp; - size_t len; - char *end; - u_char *out; - int outlen, state; - struct screen_write_ctx ctx; - const char* allow = "cpqs01234567"; - char flags[sizeof "cpqs01234567"] = ""; - u_int i, j = 0; + char *end; + size_t len; + const char *allow = "cpqs01234567"; + u_int i, j = 0; - if (wp == NULL) - return; - state = options_get_number(global_options, "set-clipboard"); - if (state != 2) - return; + if (options_get_number(global_options, "set-clipboard") != 2) + return (0); if ((end = strchr(p, ';')) == NULL) - return; + return (0); end++; if (*end == '\0') - return; + return (0); log_debug("%s: %s", __func__, end); for (i = 0; p + i != end; i++) { @@ -3108,25 +3107,53 @@ input_osc_52(struct input_ctx *ictx, const char *p) if (strcmp(end, "?") == 0) { input_osc_52_reply(ictx); - return; + return (0); } len = (strlen(end) / 4) * 3; if (len == 0) - return; + return (0); - out = xmalloc(len); - if ((outlen = b64_pton(end, out, len)) == -1) { - free(out); - return; + *out = xmalloc(len); + if ((*outlen = b64_pton(end, *out, len)) == -1) { + free(*out); + *out = NULL; + return (0); } - screen_write_start_pane(&ctx, wp, NULL); - screen_write_setselection(&ctx, flags, out, outlen); - screen_write_stop(&ctx); - notify_pane("pane-set-clipboard", wp); + return (1); +} - paste_add(NULL, out, outlen); +/* Handle the OSC 52 sequence for setting the clipboard. */ +static void +input_osc_52(struct input_ctx *ictx, const char *p) +{ + struct window_pane *wp = ictx->wp; + struct screen_write_ctx ctx; + u_char *out; + int outlen; + char flags[sizeof "cpqs01234567"] = ""; + + if (!input_osc_52_parse(ictx, p, &out, &outlen, flags)) + return; + + if (wp == NULL) { + /* Popup window. */ + if (ictx->c == NULL) { + free(out); + return; + } + tty_set_selection(&ictx->c->tty, flags, out, outlen); + paste_add(NULL, out, outlen); + } else { + /* Normal window. */ + screen_write_start_pane(&ctx, wp, NULL); + screen_write_setselection(&ctx, flags, out, outlen); + screen_write_stop(&ctx); + notify_pane("pane-set-clipboard", wp); + paste_add(NULL, out, outlen); + } + free(out); } /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */ diff --git a/popup.c b/popup.c index 70f4def4..04584b80 100644 --- a/popup.c +++ b/popup.c @@ -851,7 +851,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px, pd->job = job_run(shellcmd, argc, argv, env, s, cwd, popup_job_update_cb, popup_job_complete_cb, NULL, pd, JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy); - pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); + pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette, c); server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd); diff --git a/tmux.h b/tmux.h index 34958d4b..0f84398b 100644 --- a/tmux.h +++ b/tmux.h @@ -3011,7 +3011,7 @@ void recalculate_sizes_now(int); /* input.c */ #define INPUT_BUF_DEFAULT_SIZE 1048576 struct input_ctx *input_init(struct window_pane *, struct bufferevent *, - struct colour_palette *); + struct colour_palette *, struct client *); void input_free(struct input_ctx *); void input_reset(struct input_ctx *, int); struct evbuffer *input_pending(struct input_ctx *); diff --git a/window-copy.c b/window-copy.c index 3a147c85..c372c4b1 100644 --- a/window-copy.c +++ b/window-copy.c @@ -494,7 +494,7 @@ window_copy_view_init(struct window_mode_entry *wme, data->backing = xmalloc(sizeof *data->backing); screen_init(data->backing, sx, screen_size_y(base), UINT_MAX); - data->ictx = input_init(NULL, NULL, NULL); + data->ictx = input_init(NULL, NULL, NULL, NULL); data->mx = data->cx; data->my = screen_hsize(data->backing) + data->cy - data->oy; data->showmark = 0; diff --git a/window.c b/window.c index 9581c64f..31a8a8ee 100644 --- a/window.c +++ b/window.c @@ -1057,7 +1057,7 @@ window_pane_set_event(struct window_pane *wp) NULL, window_pane_error_callback, wp); if (wp->event == NULL) fatalx("out of memory"); - wp->ictx = input_init(wp, wp->event, &wp->palette); + wp->ictx = input_init(wp, wp->event, &wp->palette, NULL); bufferevent_enable(wp->event, EV_READ|EV_WRITE); }