diff --git a/CHANGES b/CHANGES index eb0080ec..bcd1e1c6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,29 @@ +CHANGES FROM 3.6 TO 3.6a + +* Fix a buffer overread and an infinite loop in format processing (reported by + Giorgi Kobakhia, issue 4735). + +* Allow drag in alternate screen again (issue 4743 reported by Brad King). + +* Fix y offset of mouse if status at top (issue 4738 from Michael Grant). + +* Add a missing skin tone (from Jake Stewart, issue 4736). + +* Allow characters to be combined in either order (issue 4726, reported by Jake + Stewart). + +* Fix horizontal mouse resizing when pane status lines are on (from Michael + Grant, issue 4720). + +* Fix noattr so it does not delete attributes set in the style itself (issue + 4713). + +* Newer libevents do not allow event_del on a zero'd event (issue 4706). + +* Place cursor on correct line if message-line is not 0 (issue 4707). + +* Fix compile error on FreeBSD (from Yasuhiro Kimura, issue 4701). + CHANGES FROM 3.5a TO 3.6 * Add seconds options for clock mode (issue 4697). diff --git a/attributes.c b/attributes.c index b839f06d..8eaa8897 100644 --- a/attributes.c +++ b/attributes.c @@ -31,7 +31,7 @@ attributes_tostring(int attr) if (attr == 0) return ("none"); - len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (attr & GRID_ATTR_CHARSET) ? "acs," : "", (attr & GRID_ATTR_BRIGHT) ? "bright," : "", (attr & GRID_ATTR_DIM) ? "dim," : "", @@ -45,7 +45,8 @@ attributes_tostring(int attr) (attr & GRID_ATTR_UNDERSCORE_3) ? "curly-underscore," : "", (attr & GRID_ATTR_UNDERSCORE_4) ? "dotted-underscore," : "", (attr & GRID_ATTR_UNDERSCORE_5) ? "dashed-underscore," : "", - (attr & GRID_ATTR_OVERLINE) ? "overline," : ""); + (attr & GRID_ATTR_OVERLINE) ? "overline," : "", + (attr & GRID_ATTR_NOATTR) ? "noattr," : ""); if (len > 0) buf[len - 1] = '\0'; diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 399c83de..cb30749e 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = { .name = "refresh-client", .alias = "refresh", - .args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL }, + .args = { "A:B:cC:Df:r:F:lLRSt:U", 0, 1, NULL }, .usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] " "[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE " [adjustment]", @@ -163,37 +163,6 @@ out: free(copy); } -static enum cmd_retval -cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item) -{ - struct args *args = cmd_get_args(self); - struct client *tc = cmdq_get_target_client(item); - const char *p; - u_int i; - struct cmd_find_state fs; - - p = args_get(args, 'l'); - if (p == NULL) { - if (tc->flags & CLIENT_CLIPBOARDBUFFER) - return (CMD_RETURN_NORMAL); - tc->flags |= CLIENT_CLIPBOARDBUFFER; - } else { - if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0) - return (CMD_RETURN_ERROR); - for (i = 0; i < tc->clipboard_npanes; i++) { - if (tc->clipboard_panes[i] == fs.wp->id) - break; - } - if (i != tc->clipboard_npanes) - return (CMD_RETURN_NORMAL); - tc->clipboard_panes = xreallocarray(tc->clipboard_panes, - tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes); - tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id; - } - tty_clipboard_query(&tc->tty); - return (CMD_RETURN_NORMAL); -} - static void cmd_refresh_report(struct tty *tty, const char *value) { @@ -284,8 +253,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (args_has(args, 'l')) - return (cmd_refresh_client_clipboard(self, item)); + if (args_has(args, 'l')) { + tty_clipboard_query(&tc->tty); + return (CMD_RETURN_NORMAL); + } if (args_has(args, 'F')) /* -F is an alias for -f */ server_client_set_flags(tc, args_get(args, 'F')); diff --git a/colour.c b/colour.c index 791c5fd5..88198e96 100644 --- a/colour.c +++ b/colour.c @@ -1082,22 +1082,22 @@ colour_palette_free(struct colour_palette *p) /* Get a colour from a palette. */ int -colour_palette_get(struct colour_palette *p, int c) +colour_palette_get(struct colour_palette *p, int n) { if (p == NULL) return (-1); - if (c >= 90 && c <= 97) - c = 8 + c - 90; - else if (c & COLOUR_FLAG_256) - c &= ~COLOUR_FLAG_256; - else if (c >= 8) + if (n >= 90 && n <= 97) + n = 8 + n - 90; + else if (n & COLOUR_FLAG_256) + n &= ~COLOUR_FLAG_256; + else if (n >= 8) return (-1); - if (p->palette != NULL && p->palette[c] != -1) - return (p->palette[c]); - if (p->default_palette != NULL && p->default_palette[c] != -1) - return (p->default_palette[c]); + if (p->palette != NULL && p->palette[n] != -1) + return (p->palette[n]); + if (p->default_palette != NULL && p->default_palette[n] != -1) + return (p->default_palette[n]); return (-1); } @@ -1107,15 +1107,14 @@ colour_palette_set(struct colour_palette *p, int n, int c) { u_int i; - if (p == NULL || n > 255) + if (p == NULL || n < 0 || n > 255) return (0); if (c == -1 && p->palette == NULL) return (0); - if (c != -1 && p->palette == NULL) { - if (p->palette == NULL) - p->palette = xcalloc(256, sizeof *p->palette); + if (p->palette == NULL) { + p->palette = xcalloc(256, sizeof *p->palette); for (i = 0; i < 256; i++) p->palette[i] = -1; } diff --git a/environ.c b/environ.c index 63d47946..039d3a4a 100644 --- a/environ.c +++ b/environ.c @@ -263,11 +263,6 @@ environ_for_session(struct session *s, int no_TERM) environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux"); environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion()); environ_set(env, "COLORTERM", 0, "truecolor"); - } else { - environ_unset(env, "TERM"); - environ_unset(env, "TERM_PROGRAM"); - environ_unset(env, "TERM_PROGRAM_VERSION"); - environ_unset(env, "COLORTERM"); } #ifdef HAVE_SYSTEMD diff --git a/format-draw.c b/format-draw.c index efc6ab1a..c8cb74b6 100644 --- a/format-draw.c +++ b/format-draw.c @@ -1104,8 +1104,6 @@ format_width(const char *expanded) more = utf8_append(&ud, *cp); if (more == UTF8_DONE) width += ud.width; - else - cp -= ud.have; } else if (*cp > 0x1f && *cp < 0x7f) { width++; cp++; diff --git a/format.c b/format.c index 17a9dd53..3d498b34 100644 --- a/format.c +++ b/format.c @@ -5545,7 +5545,8 @@ format_expand1(struct format_expand_state *es, const char *fmt) buf[off++] = *fmt++; continue; } - fmt++; + if (*fmt++ == '\0') + break; ch = (u_char)*fmt++; switch (ch) { diff --git a/input.c b/input.c index 3a61ec26..58a1b091 100644 --- a/input.c +++ b/input.c @@ -3069,18 +3069,41 @@ input_osc_133(struct input_ctx *ictx, const char *p) } } +/* Handle OSC 52 reply. */ +static void +input_osc_52_reply(struct input_ctx *ictx) +{ + struct paste_buffer *pb; + int state; + const char *buf; + size_t len; + + state = options_get_number(global_options, "get-clipboard"); + if (state == 0) + return; + if (state == 1) { + if ((pb = paste_get_top(NULL)) == NULL) + return; + buf = paste_buffer_data(pb, &len); + if (ictx->input_end == INPUT_END_BEL) + input_reply_clipboard(ictx->event, buf, len, "\007"); + else + input_reply_clipboard(ictx->event, buf, len, "\033\\"); + return; + } + 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) { struct window_pane *wp = ictx->wp; + size_t len; char *end; - const char *buf = NULL; - size_t len = 0; u_char *out; int outlen, state; struct screen_write_ctx ctx; - struct paste_buffer *pb; const char* allow = "cpqs01234567"; char flags[sizeof "cpqs01234567"] = ""; u_int i, j = 0; @@ -3105,12 +3128,7 @@ input_osc_52(struct input_ctx *ictx, const char *p) log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags); if (strcmp(end, "?") == 0) { - if ((pb = paste_get_top(NULL)) != NULL) - buf = paste_buffer_data(pb, &len); - if (ictx->input_end == INPUT_END_BEL) - input_reply_clipboard(ictx->event, buf, len, "\007"); - else - input_reply_clipboard(ictx->event, buf, len, "\033\\"); + input_osc_52_reply(ictx); return; } @@ -3169,6 +3187,7 @@ input_osc_104(struct input_ctx *ictx, const char *p) free(copy); } +/* Send a clipboard reply. */ void input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len, const char *end) @@ -3305,6 +3324,9 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx) xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx); tty_puts(&c->tty, s); break; + case INPUT_REQUEST_CLIPBOARD: + tty_putcode_ss(&c->tty, TTYC_MS, "", "?"); + break; case INPUT_REQUEST_QUEUE: break; } @@ -3312,6 +3334,39 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx) return (0); } +/* Handle a palette reply. */ +static void +input_request_palette_reply(struct input_request *ir, void *data) +{ + struct input_request_palette_data *pd = data; + + input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end); +} + +/* Handle a clipboard reply. */ +static void +input_request_clipboard_reply(struct input_request *ir, void *data) +{ + struct input_ctx *ictx = ir->ictx; + struct input_request_clipboard_data *cd = data; + int state; + char *copy; + + state = options_get_number(global_options, "get-clipboard"); + if (state == 0 || state == 1) + return; + if (state == 3) { + copy = xmalloc(cd->len); + memcpy(copy, cd->buf, cd->len); + paste_add(NULL, copy, cd->len); + } + + if (ir->idx == INPUT_END_BEL) + input_reply_clipboard(ictx->event, cd->buf, cd->len, "\007"); + else + input_reply_clipboard(ictx->event, cd->buf, cd->len, "\033\\"); +} + /* Handle a reply to a request. */ void input_request_reply(struct client *c, enum input_request_type type, void *data) @@ -3321,11 +3376,18 @@ input_request_reply(struct client *c, enum input_request_type type, void *data) int complete = 0; TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) { - if (ir->type == type && pd->idx == ir->idx) { + if (ir->type != type) { + input_free_request(ir); + continue; + } + if (type == INPUT_REQUEST_PALETTE && pd->idx == ir->idx) { + found = ir; + break; + } + if (type == INPUT_REQUEST_CLIPBOARD) { found = ir; break; } - input_free_request(ir); } if (found == NULL) return; @@ -3335,8 +3397,11 @@ input_request_reply(struct client *c, enum input_request_type type, void *data) break; if (ir->type == INPUT_REQUEST_QUEUE) input_send_reply(ir->ictx, ir->data); - else if (ir == found && ir->type == INPUT_REQUEST_PALETTE) { - input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end); + else if (ir == found) { + if (ir->type == INPUT_REQUEST_PALETTE) + input_request_palette_reply(ir, data); + else if (ir->type == INPUT_REQUEST_CLIPBOARD) + input_request_clipboard_reply(ir, data); complete = 1; } input_free_request(ir); diff --git a/key-bindings.c b/key-bindings.c index de7cef04..436bf032 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -442,7 +442,7 @@ key_bindings_init(void) "bind -n MouseDown1Pane { select-pane -t=; send -M }", /* Mouse button 1 drag on pane. */ - "bind -n MouseDrag1Pane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }", + "bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }", /* Mouse wheel up on pane. */ "bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }", diff --git a/layout.c b/layout.c index 8087a9e7..def9c970 100644 --- a/layout.c +++ b/layout.c @@ -1103,9 +1103,8 @@ int layout_spread_cell(struct window *w, struct layout_cell *parent) { struct layout_cell *lc; - struct style *sb_style = &w->active->scrollbar_style; u_int number, each, size, this, remainder; - int change, changed, status, scrollbars; + int change, changed, status; number = 0; TAILQ_FOREACH (lc, &parent->cells, entry) @@ -1113,14 +1112,9 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) if (number <= 1) return (0); status = options_get_number(w->options, "pane-border-status"); - scrollbars = options_get_number(w->options, "pane-scrollbars"); - if (parent->type == LAYOUT_LEFTRIGHT) { - if (scrollbars) - size = parent->sx - sb_style->width + sb_style->pad; - else - size = parent->sx; - } + if (parent->type == LAYOUT_LEFTRIGHT) + size = parent->sx; else if (parent->type == LAYOUT_TOPBOTTOM) { if (layout_add_horizontal_border(w, parent, status)) size = parent->sy - 1; diff --git a/options-table.c b/options-table.c index 8989c264..447fb52e 100644 --- a/options-table.c +++ b/options-table.c @@ -84,6 +84,9 @@ static const char *options_table_popup_border_lines_list[] = { static const char *options_table_set_clipboard_list[] = { "off", "external", "on", NULL }; +static const char *options_table_get_clipboard_list[] = { + "off", "buffer", "request", "both", NULL +}; static const char *options_table_window_size_list[] = { "largest", "smallest", "manual", "latest", NULL }; @@ -405,6 +408,18 @@ const struct options_table_entry options_table[] = { .text = "Whether to send focus events to applications." }, + { .name = "get-clipboard", + .type = OPTIONS_TABLE_CHOICE, + .scope = OPTIONS_TABLE_SERVER, + .choices = options_table_get_clipboard_list, + .default_num = 1, + .text = "When an application requests the clipboard, whether to " + "ignore the request ('off'); respond with the newest buffer " + "('buffer'); request the clipboard from the most recently " + "used terminal ('request'); or to request the clipboard, " + "create a buffer, and send it to the application ('both')." + }, + { .name = "history-file", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, diff --git a/regress/combine-test.result b/regress/combine-test.result index 0d2afb5e..a08539fb 100644 --- a/regress/combine-test.result +++ b/regress/combine-test.result @@ -4,7 +4,7 @@ Λ̊1 🏻2 👍🏻3 -👍🏻 👍🏻4 +👍🏻 👍🏻4 🤷‍♂️5 ♂️7 🤷‍♂️8 diff --git a/screen-redraw.c b/screen-redraw.c index 71cdf542..c13fe23d 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1312,6 +1312,11 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, int yoff = wp->yoff; struct visible_ranges *vr; + if (ctx->statustop) { + sb_y += ctx->statuslines; + sy += ctx->statuslines; + } + /* Set up style for slider. */ gc = sb_style->gc; memcpy(&slgc, &gc, sizeof slgc); diff --git a/screen-write.c b/screen-write.c index 96cdeab4..00d72950 100644 --- a/screen-write.c +++ b/screen-write.c @@ -2207,6 +2207,8 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc) case HANGULJAMO_STATE_NOT_HANGULJAMO: if (utf8_should_combine(&last.data, ud)) force_wide = 1; + else if (utf8_should_combine(ud, &last.data)) + force_wide = 1; else if (!utf8_has_zwj(&last.data)) return (0); break; diff --git a/screen.c b/screen.c index a7a13af2..d82784c5 100644 --- a/screen.c +++ b/screen.c @@ -594,8 +594,12 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, if (COLOUR_DEFAULT(dst->bg)) dst->bg = src->bg; utf8_copy(&dst->data, &src->data); - dst->attr = src->attr; dst->flags = src->flags; + + if (dst->attr & GRID_ATTR_NOATTR) + dst->attr |= (src->attr & GRID_ATTR_CHARSET); + else + dst->attr |= src->attr; } /* Reflow wrapped lines. */ diff --git a/server-client.c b/server-client.c index d93bd54b..e62e9b3b 100644 --- a/server-client.c +++ b/server-client.c @@ -617,7 +617,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py, pane_status_line = -1; /* not used */ /* Check if point is within the pane or scrollbar. */ - if (((pane_status != PANE_STATUS_OFF && py != pane_status_line) || + if (((pane_status != PANE_STATUS_OFF && + py != pane_status_line && py != wp->yoff + wp->sy) || (wp->yoff == 0 && py < wp->sy) || ((int)py >= wp->yoff && py < wp->yoff + wp->sy)) && ((sb_pos == PANE_SCROLLBARS_RIGHT && @@ -1302,7 +1303,11 @@ have_event: if (c->tty.mouse_scrolling_flag == 0 && where == SCROLLBAR_SLIDER) { c->tty.mouse_scrolling_flag = 1; - c->tty.mouse_slider_mpos = sl_mpos; + if (m->statusat == 0) { + c->tty.mouse_slider_mpos = sl_mpos + + m->statuslines; + } else + c->tty.mouse_slider_mpos = sl_mpos; } break; case WHEEL: diff --git a/style.c b/style.c index ef3bb225..4acc17dd 100644 --- a/style.c +++ b/style.c @@ -218,20 +218,23 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in) sy->gc.attr = 0; else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) { if (strcmp(tmp + 2, "attr") == 0) - value = 0xffff & ~GRID_ATTR_CHARSET; - else if ((value = attributes_fromstring(tmp + 2)) == -1) - goto error; - sy->gc.attr &= ~value; + sy->gc.attr |= GRID_ATTR_NOATTR; + else { + value = attributes_fromstring(tmp + 2); + if (value == -1) + goto error; + sy->gc.attr &= ~value; + } } else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) { - n = strtonum(tmp + 6, 0, UINT_MAX, &errstr); - if (errstr != NULL) - goto error; - sy->width = (int)n; + n = strtonum(tmp + 6, 0, UINT_MAX, &errstr); + if (errstr != NULL) + goto error; + sy->width = (int)n; } else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) { - n = strtonum(tmp + 4, 0, UINT_MAX, &errstr); - if (errstr != NULL) - goto error; - sy->pad = (int)n; + n = strtonum(tmp + 4, 0, UINT_MAX, &errstr); + if (errstr != NULL) + goto error; + sy->pad = (int)n; } else { if ((value = attributes_fromstring(tmp)) == -1) goto error; @@ -344,13 +347,13 @@ style_tostring(struct style *sy) attributes_tostring(gc->attr)); comma = ","; } - if (sy->width >= 0) { - xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma, + if (sy->width >= 0) { + xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma, sy->width); comma = ","; } - if (sy->pad >= 0) { - xsnprintf(s + off, sizeof s - off, "%spad=%u", comma, + if (sy->pad >= 0) { + xsnprintf(s + off, sizeof s - off, "%spad=%u", comma, sy->pad); comma = ","; } diff --git a/tmux.1 b/tmux.1 index 5a17095d..404909bd 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1363,12 +1363,11 @@ and sets an environment variable for the newly created session; it may be specified multiple times. .Tg refresh .It Xo Ic refresh-client -.Op Fl cDLRSU +.Op Fl cDlLRSU .Op Fl A Ar pane:state .Op Fl B Ar name:what:format .Op Fl C Ar size .Op Fl f Ar flags -.Op Fl l Op Ar target-pane .Op Fl r Ar pane:report .Op Fl t Ar target-client .Op Ar adjustment @@ -1489,11 +1488,7 @@ a colon, then a report escape sequence. .Fl l requests the clipboard from the client using the .Xr xterm 1 -escape sequence. -If -.Ar target-pane -is given, the clipboard is sent (in encoded form), otherwise it is stored in a -new paste buffer. +escape sequence and stores it in a new paste buffer. .Pp .Fl L , .Fl R , @@ -4241,6 +4236,32 @@ passed through to applications running in .Nm . Attached clients should be detached and attached again after changing this option. +.It Xo Ic get-clipboard +.Op Ic both | request | buffer | off +.Xc +Controls the behaviour when an application requests the clipboard from +.Nm . +.Pp +If +.Ic off , +the request is ignored; +if +.Ic buffer , +.Nm +responds with the newest paste buffer; +.Ic request +causes +.Nm +to request the clipboard from the most recently used client (if possible) and +send the reply (if any) back to the application; +.Ic buffer +is the same as +.Ic request +but also creates a paste buffer. +.Pp +See also the +.Ic set-clipboard +option. .It Ic history-file Ar path If not empty, a file to which .Nm @@ -6135,7 +6156,6 @@ The following variables are available, where appropriate: .It Li "insert_flag" Ta "" Ta "Pane insert flag" .It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag" .It Li "keypad_flag" Ta "" Ta "Pane keypad flag" -.It Li "last_session_index" Ta "" Ta "Index of last session" .It Li "last_window_index" Ta "" Ta "Index of last window in session" .It Li "line" Ta "" Ta "Line number in the list" .It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop" @@ -6227,7 +6247,6 @@ The following variables are available, where appropriate: .It Li "session_group_size" Ta "" Ta "Size of session group" .It Li "session_grouped" Ta "" Ta "1 if session in a group" .It Li "session_id" Ta "" Ta "Unique session ID" -.It Li "session_index" Ta "" Ta "Index of session" .It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached" .It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane" diff --git a/tmux.h b/tmux.h index d62b0a96..cc5dfecb 100644 --- a/tmux.h +++ b/tmux.h @@ -727,6 +727,7 @@ struct colour_palette { #define GRID_ATTR_UNDERSCORE_4 0x800 #define GRID_ATTR_UNDERSCORE_5 0x1000 #define GRID_ATTR_OVERLINE 0x2000 +#define GRID_ATTR_NOATTR 0x4000 /* All underscore attributes. */ #define GRID_ATTR_ALL_UNDERSCORE \ @@ -1129,6 +1130,7 @@ struct window_mode_entry { /* Type of request to client. */ enum input_request_type { INPUT_REQUEST_PALETTE, + INPUT_REQUEST_CLIPBOARD, INPUT_REQUEST_QUEUE }; @@ -1138,6 +1140,12 @@ struct input_request_palette_data { int c; }; +/* Clipboard request reply data. */ +struct input_request_clipboard_data { + char *buf; + size_t len; +}; + /* Request sent to client on behalf of pane. */ TAILQ_HEAD(input_requests, input_request); @@ -2014,7 +2022,7 @@ struct client { #define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL #define CLIENT_CONTROL_WAITEXIT 0x200000000ULL #define CLIENT_WINDOWSIZECHANGED 0x400000000ULL -#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL +/* 0x800000000ULL unused */ #define CLIENT_BRACKETPASTING 0x1000000000ULL #define CLIENT_ASSUMEPASTING 0x2000000000ULL #define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL diff --git a/tty-keys.c b/tty-keys.c index 77254591..7474621c 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1301,12 +1301,11 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size, static int tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) { - struct client *c = tty->client; - struct window_pane *wp; - size_t end, terminator = 0, needed; - char *copy, *out; - int outlen; - u_int i; + struct client *c = tty->client; + size_t end, terminator = 0, needed; + char *copy, *out; + int outlen; + struct input_request_clipboard_data cd; *size = 0; @@ -1364,12 +1363,6 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) buf++; end--; - /* If we did not request this, ignore it. */ - if (~tty->flags & TTY_OSC52QUERY) - return (0); - tty->flags &= ~TTY_OSC52QUERY; - evtimer_del(&tty->clipboard_timer); - /* It has to be a string so copy it. */ copy = xmalloc(end + 1); memcpy(copy, buf, end); @@ -1384,22 +1377,22 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) return (0); } free(copy); - - /* Create a new paste buffer and forward to panes. */ log_debug("%s: %.*s", __func__, outlen, out); - if (c->flags & CLIENT_CLIPBOARDBUFFER) { - paste_add(NULL, out, outlen); - c->flags &= ~CLIENT_CLIPBOARDBUFFER; - } - for (i = 0; i < c->clipboard_npanes; i++) { - wp = window_pane_find_by_id(c->clipboard_panes[i]); - if (wp != NULL) - input_reply_clipboard(wp->event, out, outlen, "\033\\"); - } - free(c->clipboard_panes); - c->clipboard_panes = NULL; - c->clipboard_npanes = 0; + /* Set reply if any. */ + cd.buf = out; + cd.len = outlen; + input_request_reply(c, INPUT_REQUEST_CLIPBOARD, &cd); + + /* Create a buffer if requested. */ + if (tty->flags & TTY_OSC52QUERY) { + paste_add(NULL, out, outlen); + out = NULL; + evtimer_del(&tty->clipboard_timer); + tty->flags &= ~TTY_OSC52QUERY; + } + + free(out); return (0); } diff --git a/tty.c b/tty.c index aa522d6b..44e92e52 100644 --- a/tty.c +++ b/tty.c @@ -3300,12 +3300,6 @@ static void tty_clipboard_query_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; - struct client *c = tty->client; - - c->flags &= ~CLIENT_CLIPBOARDBUFFER; - free(c->clipboard_panes); - c->clipboard_panes = NULL; - c->clipboard_npanes = 0; tty->flags &= ~TTY_OSC52QUERY; } @@ -3315,10 +3309,9 @@ tty_clipboard_query(struct tty *tty) { struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT }; - if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY)) - return; - tty_putcode_ss(tty, TTYC_MS, "", "?"); - - tty->flags |= TTY_OSC52QUERY; - evtimer_add(&tty->clipboard_timer, &tv); + if ((tty->flags & TTY_STARTED) && (~tty->flags & TTY_OSC52QUERY)) { + tty_putcode_ss(tty, TTYC_MS, "", "?"); + tty->flags |= TTY_OSC52QUERY; + evtimer_add(&tty->clipboard_timer, &tv); + } } diff --git a/utf8-combined.c b/utf8-combined.c index 635ae92c..1eee3b82 100644 --- a/utf8-combined.c +++ b/utf8-combined.c @@ -122,6 +122,7 @@ utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add) case 0x1F47C: case 0x1F481: case 0x1F482: + case 0x1F483: case 0x1F485: case 0x1F486: case 0x1F487: diff --git a/window-copy.c b/window-copy.c index f8d2fb7e..313e08a1 100644 --- a/window-copy.c +++ b/window-copy.c @@ -627,7 +627,7 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp, new_slider_y = sb_top - wp->yoff + (sb_height - slider_height); } else { /* Slider is somewhere in the middle. */ - new_slider_y = my - wp->yoff - sl_mpos + 1; + new_slider_y = my - wp->yoff - sl_mpos; } if (TAILQ_FIRST(&wp->modes) == NULL || diff --git a/window.c b/window.c index 4660cd18..fff51707 100644 --- a/window.c +++ b/window.c @@ -1826,7 +1826,7 @@ window_pane_mode(struct window_pane *wp) int window_pane_show_scrollbar(struct window_pane *wp, int sb_option) { - if (SCREEN_IS_ALTERNATE(wp->screen)) + if (SCREEN_IS_ALTERNATE(&wp->base)) return (0); if (sb_option == PANE_SCROLLBARS_ALWAYS || (sb_option == PANE_SCROLLBARS_MODAL &&