diff options
Diffstat (limited to 'window-copy.c')
-rw-r--r-- | window-copy.c | 464 |
1 files changed, 351 insertions, 113 deletions
diff --git a/window-copy.c b/window-copy.c index 2a47e9b0..38e87b67 100644 --- a/window-copy.c +++ b/window-copy.c @@ -22,6 +22,7 @@ #include <regex.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include "tmux.h" @@ -205,6 +206,8 @@ struct window_copy_mode_data { struct screen *backing; int backing_written; /* backing display started */ + int viewmode; /* view mode entered */ + u_int oy; /* number of lines scrolled up */ u_int selx; /* beginning of selection */ @@ -254,15 +257,18 @@ struct window_copy_mode_data { int searchtype; int searchregex; char *searchstr; - bitstr_t *searchmark; - u_int searchcount; + u_char *searchmark; + int searchcount; + int searchmore; int searchthis; int searchx; int searchy; int searcho; + u_char searchgen; int timeout; /* search has timed out */ -#define WINDOW_COPY_SEARCH_TIMEOUT 10 +#define WINDOW_COPY_SEARCH_TIMEOUT 10000 +#define WINDOW_COPY_SEARCH_ALL_TIMEOUT 200 int jumptype; char jumpchar; @@ -295,6 +301,48 @@ window_copy_scroll_timer(__unused int fd, __unused short events, void *arg) } } +static struct screen * +window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, + u_int *cy, int trim) +{ + struct screen *dst; + u_int sy; + const struct grid_line *gl; + + dst = xcalloc(1, sizeof *dst); + + sy = screen_hsize(src) + screen_size_y(src); + if (trim) { + while (sy > screen_hsize(src)) { + gl = grid_peek_line(src->grid, sy - 1); + if (gl->cellused != 0) + break; + sy--; + } + } + log_debug("%s: target screen is %ux%u, source %ux%u", __func__, + screen_size_x(src), sy, screen_size_x(hint), + screen_hsize(src) + screen_size_y(src)); + screen_init(dst, screen_size_x(src), sy, screen_hlimit(src)); + grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); + + dst->grid->sy = sy - screen_hsize(src); + dst->grid->hsize = screen_hsize(src); + dst->grid->hscrolled = src->grid->hscrolled; + if (src->cy > dst->grid->sy - 1) { + dst->cx = 0; + dst->cy = dst->grid->sy - 1; + } else { + dst->cx = src->cx; + dst->cy = src->cy; + } + + screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1, + 0, cx, cy); + + return (dst); +} + static struct window_copy_mode_data * window_copy_common_init(struct window_mode_entry *wme) { @@ -317,9 +365,7 @@ window_copy_common_init(struct window_mode_entry *wme) data->searchregex = 0; data->searchstr = NULL; } - data->searchmark = NULL; data->searchx = data->searchy = data->searcho = -1; - data->timeout = 0; data->jumptype = WINDOW_COPY_OFF; data->jumpchar = '\0'; @@ -336,19 +382,25 @@ static struct screen * window_copy_init(struct window_mode_entry *wme, __unused struct cmd_find_state *fs, struct args *args) { - struct window_pane *wp = wme->wp; + struct window_pane *wp = wme->swp; struct window_copy_mode_data *data; + struct screen *base = &wp->base; struct screen_write_ctx ctx; - u_int i; + u_int i, cx, cy; data = window_copy_common_init(wme); + data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy, + wme->swp != wme->wp); - if (wp->fd != -1 && wp->disabled++ == 0) - bufferevent_disable(wp->event, EV_READ|EV_WRITE); - - data->backing = &wp->base; - data->cx = data->backing->cx; - data->cy = data->backing->cy; + if (cy < screen_hsize(data->backing)) { + data->cx = cx; + data->cy = 0; + data->oy = screen_hsize(data->backing) - cy; + } else { + data->cx = data->backing->cx; + data->cy = data->backing->cy; + data->oy = 0; + } data->scroll_exit = args_has(args, 'e'); data->hide_position = args_has(args, 'H'); @@ -356,7 +408,7 @@ window_copy_init(struct window_mode_entry *wme, data->screen.cx = data->cx; data->screen.cy = data->cy; - screen_write_start(&ctx, NULL, &data->screen); + screen_write_start(&ctx, &data->screen); for (i = 0; i < screen_size_y(&data->screen); i++) window_copy_write_line(wme, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy, 0); @@ -375,6 +427,7 @@ window_copy_view_init(struct window_mode_entry *wme, struct screen *s; data = window_copy_common_init(wme); + data->viewmode = 1; data->backing = s = xmalloc(sizeof *data->backing); screen_init(s, screen_size_x(base), screen_size_y(base), UINT_MAX); @@ -385,23 +438,17 @@ window_copy_view_init(struct window_mode_entry *wme, static void window_copy_free(struct window_mode_entry *wme) { - struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; evtimer_del(&data->dragtimer); - if (wp->fd != -1 && --wp->disabled == 0) - bufferevent_enable(wp->event, EV_READ|EV_WRITE); - free(data->searchmark); free(data->searchstr); - if (data->backing != &wp->base) { - screen_free(data->backing); - free(data->backing); - } - screen_free(&data->screen); + screen_free(data->backing); + free(data->backing); + screen_free(&data->screen); free(data); } @@ -425,13 +472,10 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap) struct grid_cell gc; u_int old_hsize, old_cy; - if (backing == &wp->base) - return; - memcpy(&gc, &grid_default_cell, sizeof gc); old_hsize = screen_hsize(data->backing); - screen_write_start(&back_ctx, NULL, backing); + screen_write_start(&back_ctx, backing); if (data->backing_written) { /* * On the second or later line, do a CRLF before writing @@ -447,7 +491,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap) data->oy += screen_hsize(data->backing) - old_hsize; - screen_write_start(&ctx, wp, &data->screen); + screen_write_start_pane(&ctx, wp, &data->screen); /* * If the history has changed, draw the top line. @@ -661,31 +705,18 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft) } static void -window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) +window_copy_size_changed(struct window_mode_entry *wme) { - struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; struct screen *s = &data->screen; - struct screen_write_ctx ctx; - int search; - - screen_resize(s, sx, sy, 1); - if (data->backing != &wp->base) - screen_resize(data->backing, sx, sy, 1); - - if (data->cy > sy - 1) - data->cy = sy - 1; - if (data->cx > sx) - data->cx = sx; - if (data->oy > screen_hsize(data->backing)) - data->oy = screen_hsize(data->backing); + struct screen_write_ctx ctx; + int search = (data->searchmark != NULL); - search = (data->searchmark != NULL); window_copy_clear_selection(wme); window_copy_clear_marks(wme); - screen_write_start(&ctx, NULL, s); - window_copy_write_lines(wme, &ctx, 0, screen_size_y(s) - 1); + screen_write_start(&ctx, s); + window_copy_write_lines(wme, &ctx, 0, screen_size_y(s)); screen_write_stop(&ctx); if (search && !data->timeout) @@ -693,7 +724,25 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) data->searchx = data->cx; data->searchy = data->cy; data->searcho = data->oy; +} + +static void +window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) +{ + struct window_copy_mode_data *data = wme->data; + struct screen *s = &data->screen; + + screen_resize(s, sx, sy, 0); + screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); + + if (data->cy > sy - 1) + data->cy = sy - 1; + if (data->cx > sx) + data->cx = sx; + if (data->oy > screen_hsize(data->backing)) + data->oy = screen_hsize(data->backing); + window_copy_size_changed(wme); window_copy_redraw_screen(wme); } @@ -1043,14 +1092,15 @@ window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; struct window_copy_mode_data *data = wme->data; + struct screen *s = data->backing; u_int oy; - oy = screen_hsize(data->backing) + data->cy - data->oy; + oy = screen_hsize(s) + data->cy - data->oy; if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely) window_copy_other_end(wme); data->cy = screen_size_y(&data->screen) - 1; - data->cx = window_copy_find_length(wme, data->cy); + data->cx = window_copy_find_length(wme, screen_hsize(s) + data->cy); data->oy = 0; if (data->searchmark != NULL && !data->timeout) @@ -1690,11 +1740,10 @@ window_copy_cmd_copy_pipe_no_clear(struct window_copy_cmd_state *cs) if (cs->args->argc == 3) prefix = format_single(NULL, cs->args->argv[2], c, s, wl, wp); - if (s != NULL && *cs->args->argv[1] != '\0') { + if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); - window_copy_copy_pipe(wme, s, prefix, command); - free(command); - } + window_copy_copy_pipe(wme, s, prefix, command); + free(command); free(prefix); return (WINDOW_COPY_CMD_NOTHING); @@ -1984,6 +2033,25 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) return (action); } +static enum window_copy_cmd_action +window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_pane *wp = wme->swp; + struct window_copy_mode_data *data = wme->data; + + if (data->viewmode) + return (WINDOW_COPY_CMD_NOTHING); + + screen_free(data->backing); + free(data->backing); + data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, + NULL, wme->swp != wme->wp); + + window_copy_size_changed(wme); + return (WINDOW_COPY_CMD_REDRAW); +} + static const struct { const char *command; int minargs; @@ -2009,11 +2077,11 @@ static const struct { window_copy_cmd_copy_end_of_line }, { "copy-line", 0, 1, 0, window_copy_cmd_copy_line }, - { "copy-pipe-no-clear", 1, 2, 0, + { "copy-pipe-no-clear", 0, 2, 0, window_copy_cmd_copy_pipe_no_clear }, - { "copy-pipe", 1, 2, 0, + { "copy-pipe", 0, 2, 0, window_copy_cmd_copy_pipe }, - { "copy-pipe-and-cancel", 1, 2, 0, + { "copy-pipe-and-cancel", 0, 2, 0, window_copy_cmd_copy_pipe_and_cancel }, { "copy-selection-no-clear", 0, 1, 0, window_copy_cmd_copy_selection_no_clear }, @@ -2089,6 +2157,8 @@ static const struct { window_copy_cmd_previous_word }, { "rectangle-toggle", 0, 0, 0, window_copy_cmd_rectangle_toggle }, + { "refresh-from-pane", 0, 0, 0, + window_copy_cmd_refresh_from_pane }, { "scroll-down", 0, 0, 1, window_copy_cmd_scroll_down }, { "scroll-down-and-cancel", 0, 0, 0, @@ -2754,7 +2824,7 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex) fy = screen_hsize(data->backing) - data->oy + data->cy; screen_init(&ss, screen_write_strlen("%s", str), 1, 0); - screen_write_start(&ctx, NULL, &ss); + screen_write_start(&ctx, &ss); screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", str); screen_write_stop(&ctx); @@ -2779,6 +2849,15 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex) return (found); } +static uint64_t +window_copy_get_time(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return ((tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000ULL)); +} + static int window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, int regex) @@ -2788,18 +2867,18 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, struct screen_write_ctx ctx; struct grid *gd = s->grid; const struct grid_line *gl; - int found, cis, which = -1; + int found, cis, which = -1, stopped = 0; int cflags = REG_EXTENDED; - u_int px, py, b, nfound = 0, width; - u_int ssize = 1; + u_int px, py, i, b, nfound = 0, width; + u_int ssize = 1, start, end; char *sbuf; regex_t reg; - time_t tstart, t; + uint64_t stop = 0, tstart, t; if (ssp == NULL) { width = screen_write_strlen("%s", data->searchstr); screen_init(&ss, width, 1, 0); - screen_write_start(&ctx, NULL, &ss); + screen_write_start(&ctx, &ss); screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", data->searchstr); screen_write_stop(&ctx); @@ -2809,9 +2888,6 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, cis = window_copy_is_lowercase(data->searchstr); - free(data->searchmark); - data->searchmark = bit_alloc((gd->hsize + gd->sy) * gd->sx); - if (regex) { sbuf = xmalloc(ssize); sbuf[0] = '\0'; @@ -2824,13 +2900,18 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, return (0); } } - time(&tstart); - for (py = gd->hsize - data->oy; py > 0; py--) { - gl = grid_peek_line(gd, py - 1); - if (~gl->flags & GRID_LINE_WRAPPED) - break; - } - for (; py < gd->hsize - data->oy + gd->sy; py++) { + tstart = window_copy_get_time(); + + start = 0; + end = gd->hsize + gd->sy; + stop = window_copy_get_time() + WINDOW_COPY_SEARCH_ALL_TIMEOUT; + +again: + free(data->searchmark); + data->searchmark = xcalloc(gd->hsize + gd->sy, gd->sx); + data->searchgen = 1; + + for (py = start; py < end; py++) { px = 0; for (;;) { if (regex) { @@ -2851,34 +2932,70 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, which = nfound; b = (py * gd->sx) + px; - bit_nset(data->searchmark, b, b + width - 1); + for (i = b; i < b + width; i++) + data->searchmark[i] = data->searchgen; + if (data->searchgen == UCHAR_MAX) + data->searchgen = 1; + else + data->searchgen++; px++; } - time(&t); + t = window_copy_get_time(); if (t - tstart > WINDOW_COPY_SEARCH_TIMEOUT) { data->timeout = 1; break; } - } - if (regex) { - free(sbuf); - regfree(®); + if (stop != 0 && t > stop) { + stopped = 1; + break; + } } if (data->timeout) { window_copy_clear_marks(wme); - return (1); + goto out; } - if (which != -1) - data->searchthis = 1 + nfound - which; - else + if (stopped && stop != 0) { + /* Try again but just the visible context. */ + for (start = gd->hsize - data->oy; start > 0; start--) { + gl = grid_peek_line(gd, start - 1); + if (~gl->flags & GRID_LINE_WRAPPED) + break; + } + end = gd->hsize - data->oy + gd->sy; + stop = 0; + goto again; + } + + if (stopped) { data->searchthis = -1; - data->searchcount = nfound; + if (nfound > 1000) + data->searchcount = 1000; + else if (nfound > 100) + data->searchcount = 100; + else if (nfound > 10) + data->searchcount = 10; + else + data->searchcount = -1; + data->searchmore = 1; + } else { + if (which != -1) + data->searchthis = 1 + nfound - which; + else + data->searchthis = -1; + data->searchcount = nfound; + data->searchmore = 0; + } +out: if (ssp == &ss) screen_free(&ss); + if (regex) { + free(sbuf); + regfree(®); + } return (1); } @@ -2922,6 +3039,117 @@ window_copy_goto_line(struct window_mode_entry *wme, const char *linestr) } static void +window_copy_match_start_end(struct window_copy_mode_data *data, u_int at, + u_int *start, u_int *end) +{ + struct grid *gd = data->backing->grid; + u_int last = (gd->hsize + gd->sy) * gd->sx - 1; + u_char mark = data->searchmark[at]; + + *start = *end = at; + while (*start != 0 && data->searchmark[*start] == mark) + (*start)--; + if (data->searchmark[*start] != mark) + (*start)++; + while (*end != last && data->searchmark[*end] == mark) + (*end)++; + if (data->searchmark[*end] != mark) + (*end)--; +} + +static char * +window_copy_match_at_cursor(struct window_copy_mode_data *data) +{ + struct grid *gd = data->backing->grid; + struct grid_cell gc; + u_int at, start, end, cy, px, py; + u_int sx = screen_size_x(data->backing); + char *buf = NULL; + size_t len = 0; + + if (data->searchmark == NULL) + return (NULL); + + cy = screen_hsize(data->backing) - data->oy + data->cy; + at = (cy * sx) + data->cx; + if (data->searchmark[at] == 0) + return (NULL); + window_copy_match_start_end(data, at, &start, &end); + + /* + * Cells will not be set in the marked array unless they are valid text + * and wrapping will be taken care of, so we can just copy. + */ + for (at = start; at <= end; at++) { + py = at / sx; + px = at % (py * sx); + + grid_get_cell(gd, px, py, &gc); + buf = xrealloc(buf, len + gc.data.size + 1); + memcpy(buf + len, gc.data.data, gc.data.size); + len += gc.data.size; + } + if (len != 0) + buf[len] = '\0'; + return (buf); +} + +static void +window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy, + struct grid_cell *gc, const struct grid_cell *mgc, + const struct grid_cell *cgc) +{ + struct window_copy_mode_data *data = wme->data; + u_int mark, start, end, cy, cursor, current; + u_int sx = screen_size_x(data->backing); + + if (data->searchmark == NULL) + return; + + current = (fy * sx) + fx; + + mark = data->searchmark[current]; + if (mark == 0) + return; + + cy = screen_hsize(data->backing) - data->oy + data->cy; + cursor = (cy * sx) + data->cx; + if (data->searchmark[cursor] == mark) { + window_copy_match_start_end(data, cursor, &start, &end); + if (current >= start && current <= end) { + gc->attr = cgc->attr; + gc->fg = cgc->fg; + gc->bg = cgc->bg; + return; + } + } + + gc->attr = mgc->attr; + gc->fg = mgc->fg; + gc->bg = mgc->bg; +} + +static void +window_copy_write_one(struct window_mode_entry *wme, + struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx, + const struct grid_cell *mgc, const struct grid_cell *cgc) +{ + struct window_copy_mode_data *data = wme->data; + struct grid *gd = data->backing->grid; + struct grid_cell gc; + u_int fx; + + screen_write_cursormove(ctx, 0, py, 0); + for (fx = 0; fx < nx; fx++) { + grid_get_cell(gd, fx, fy, &gc); + if (fx + gc.data.width <= nx) { + window_copy_update_style(wme, fx, fy, &gc, mgc, cgc); + screen_write_cell(ctx, &gc); + } + } +} + +static void window_copy_write_line(struct window_mode_entry *wme, struct screen_write_ctx *ctx, u_int py) { @@ -2929,34 +3157,39 @@ window_copy_write_line(struct window_mode_entry *wme, struct window_copy_mode_data *data = wme->data; struct screen *s = &data->screen; struct options *oo = wp->window->options; - struct grid_cell gc; + struct grid_cell gc, mgc, cgc; char hdr[512]; size_t size = 0; + u_int hsize = screen_hsize(data->backing); - style_apply(&gc, oo, "mode-style"); + style_apply(&gc, oo, "mode-style", NULL); gc.flags |= GRID_FLAG_NOPALETTE; + style_apply(&mgc, oo, "copy-mode-match-style", NULL); + mgc.flags |= GRID_FLAG_NOPALETTE; + style_apply(&cgc, oo, "copy-mode-current-match-style", NULL); + cgc.flags |= GRID_FLAG_NOPALETTE; if (py == 0 && s->rupper < s->rlower && !data->hide_position) { if (data->searchmark == NULL) { if (data->timeout) { size = xsnprintf(hdr, sizeof hdr, - "(timed out) [%u/%u]", data->oy, - screen_hsize(data->backing)); + "(timed out) [%u/%u]", data->oy, hsize); } else { size = xsnprintf(hdr, sizeof hdr, - "[%u/%u]", data->oy, - screen_hsize(data->backing)); + "[%u/%u]", data->oy, hsize); } } else { - if (data->searchthis == -1) { + if (data->searchcount == -1) { size = xsnprintf(hdr, sizeof hdr, - "(%u results) [%d/%u]", data->searchcount, - data->oy, screen_hsize(data->backing)); + "[%u/%u]", data->oy, hsize); + } else if (data->searchthis == -1) { + size = xsnprintf(hdr, sizeof hdr, + "(%d%s results) [%u/%u]", data->searchcount, + data->searchmore ? "+" : "", data->oy, hsize); } else { size = xsnprintf(hdr, sizeof hdr, - "(%u/%u results) [%d/%u]", data->searchthis, - data->searchcount, data->oy, - screen_hsize(data->backing)); + "(%d/%d results) [%u/%u]", data->searchthis, + data->searchcount, data->oy, hsize); } } if (size > screen_size_x(s)) @@ -2967,16 +3200,13 @@ window_copy_write_line(struct window_mode_entry *wme, size = 0; if (size < screen_size_x(s)) { - screen_write_cursormove(ctx, 0, py, 0); - screen_write_copy(ctx, data->backing, 0, - (screen_hsize(data->backing) - data->oy) + py, - screen_size_x(s) - size, 1, data->searchmark, &gc); + window_copy_write_one(wme, ctx, py, hsize - data->oy + py, + screen_size_x(s) - size, &mgc, &cgc); } if (py == data->cy && data->cx == screen_size_x(s)) { - memcpy(&gc, &grid_default_cell, sizeof gc); screen_write_cursormove(ctx, screen_size_x(s) - 1, py, 0); - screen_write_putc(ctx, &gc, '$'); + screen_write_putc(ctx, &grid_default_cell, '$'); } } @@ -3026,7 +3256,7 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny) struct screen_write_ctx ctx; u_int i; - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); for (i = py; i < py + ny; i++) window_copy_write_line(wme, &ctx, i); screen_write_cursormove(&ctx, data->cx, data->cy, 0); @@ -3145,7 +3375,7 @@ window_copy_update_cursor(struct window_mode_entry *wme, u_int cx, u_int cy) if (data->cx == screen_size_x(s)) window_copy_redraw_lines(wme, data->cy, 1); else { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, data->cx, data->cy, 0); screen_write_stop(&ctx); } @@ -3244,7 +3474,7 @@ window_copy_set_selection(struct window_mode_entry *wme, int may_redraw, } /* Set colours and selection. */ - style_apply(&gc, oo, "mode-style"); + style_apply(&gc, oo, "mode-style", NULL); gc.flags |= GRID_FLAG_NOPALETTE; screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, data->modekeys, &gc); @@ -3287,8 +3517,12 @@ window_copy_get_selection(struct window_mode_entry *wme, size_t *len) u_int firstsx, lastex, restex, restsx, selx; int keys; - if (data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE) - return (NULL); + if (data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE) { + buf = window_copy_match_at_cursor(data); + if (buf != NULL) + *len = strlen(buf); + return (buf); + } buf = xmalloc(1); off = 0; @@ -3394,7 +3628,7 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix, struct screen_write_ctx ctx; if (options_get_number(global_options, "set-clipboard") != 0) { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_setselection(&ctx, buf, len); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); @@ -3415,8 +3649,13 @@ window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s, if (buf == NULL) return; - job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT); - bufferevent_write(job_get_event(job), buf, len); + if (cmd == NULL || *cmd == '\0') + cmd = options_get_string(global_options, "copy-command"); + if (cmd != NULL && *cmd != '\0') { + job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT, + -1, -1); + bufferevent_write(job_get_event(job), buf, len); + } window_copy_copy_buffer(wme, prefix, buf, len); } @@ -3446,7 +3685,7 @@ window_copy_append_selection(struct window_mode_entry *wme) return; if (options_get_number(global_options, "set-clipboard") != 0) { - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_setselection(&ctx, buf, len); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); @@ -4120,7 +4359,6 @@ window_copy_cursor_previous_word_pos(struct window_mode_entry *wme, data->oy >= screen_hsize(data->backing) - 1)) goto out; - py--; py = screen_hsize(data->backing) + data->cy - data->oy; @@ -4210,7 +4448,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny) window_copy_search_marks(wme, NULL, data->searchregex); window_copy_update_selection(wme, 0, 0); - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0, 0); screen_write_deleteline(&ctx, ny, 8); window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny); @@ -4246,7 +4484,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny) window_copy_search_marks(wme, NULL, data->searchregex); window_copy_update_selection(wme, 0, 0); - screen_write_start(&ctx, wp, NULL); + screen_write_start_pane(&ctx, wp, NULL); screen_write_cursormove(&ctx, 0, 0, 0); screen_write_insertline(&ctx, ny, 8); window_copy_write_lines(wme, &ctx, 0, ny); @@ -4329,7 +4567,7 @@ window_copy_start_drag(struct client *c, struct mouse_event *m) data->selflag = SEL_CHAR; switch (data->selflag) { case SEL_WORD: - if (data->ws) { + if (data->ws != NULL) { window_copy_update_cursor(wme, x, y); window_copy_cursor_previous_word_pos(wme, data->ws, 0, &x, &y); |