Home | History | Annotate | Line # | Download | only in dist
      1 /* $OpenBSD$ */
      2 
      3 /*
      4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott (at) gmail.com>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/types.h>
     20 
     21 #include <ctype.h>
     22 #include <regex.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <time.h>
     26 
     27 #include "tmux.h"
     28 
     29 struct window_copy_mode_data;
     30 
     31 static const char *window_copy_key_table(struct window_mode_entry *);
     32 static void	window_copy_command(struct window_mode_entry *, struct client *,
     33 		    struct session *, struct winlink *, struct args *,
     34 		    struct mouse_event *);
     35 static struct screen *window_copy_init(struct window_mode_entry *,
     36 		    struct cmd_find_state *, struct args *);
     37 static struct screen *window_copy_view_init(struct window_mode_entry *,
     38 		    struct cmd_find_state *, struct args *);
     39 static void	window_copy_free(struct window_mode_entry *);
     40 static void	window_copy_resize(struct window_mode_entry *, u_int, u_int);
     41 static void	window_copy_formats(struct window_mode_entry *,
     42 		    struct format_tree *);
     43 static struct screen *window_copy_get_screen(struct window_mode_entry *);
     44 static void	window_copy_scroll1(struct window_mode_entry *,
     45 		    struct window_pane *wp, int, u_int, int);
     46 static void	window_copy_pageup1(struct window_mode_entry *, int);
     47 static int	window_copy_pagedown1(struct window_mode_entry *, int, int);
     48 static void	window_copy_next_paragraph(struct window_mode_entry *);
     49 static void	window_copy_previous_paragraph(struct window_mode_entry *);
     50 static void	window_copy_redraw_selection(struct window_mode_entry *, u_int);
     51 static void	window_copy_redraw_lines(struct window_mode_entry *, u_int,
     52 		    u_int);
     53 static void	window_copy_redraw_screen(struct window_mode_entry *);
     54 static void	window_copy_write_line(struct window_mode_entry *,
     55 		    struct screen_write_ctx *, u_int);
     56 static void	window_copy_write_lines(struct window_mode_entry *,
     57 		    struct screen_write_ctx *, u_int, u_int);
     58 static char    *window_copy_match_at_cursor(struct window_copy_mode_data *);
     59 static void	window_copy_scroll_to(struct window_mode_entry *, u_int, u_int,
     60 		    int);
     61 static int	window_copy_search_compare(struct grid *, u_int, u_int,
     62 		    struct grid *, u_int, int);
     63 static int	window_copy_search_lr(struct grid *, struct grid *, u_int *,
     64 		    u_int, u_int, u_int, int);
     65 static int	window_copy_search_rl(struct grid *, struct grid *, u_int *,
     66 		    u_int, u_int, u_int, int);
     67 static int	window_copy_last_regex(struct grid *, u_int, u_int, u_int,
     68 		    u_int, u_int *, u_int *, const char *, const regex_t *,
     69 		    int);
     70 static int	window_copy_search_mark_at(struct window_copy_mode_data *,
     71 		    u_int, u_int, u_int *);
     72 static char    *window_copy_stringify(struct grid *, u_int, u_int, u_int,
     73 		    char *, u_int *);
     74 static void	window_copy_cstrtocellpos(struct grid *, u_int, u_int *,
     75 		    u_int *, const char *);
     76 static int	window_copy_search_marks(struct window_mode_entry *,
     77 		    struct screen *, int, int);
     78 static void	window_copy_clear_marks(struct window_mode_entry *);
     79 static int	window_copy_is_lowercase(const char *);
     80 static void	window_copy_search_back_overlap(struct grid *, regex_t *,
     81 		    u_int *, u_int *, u_int *, u_int);
     82 static int	window_copy_search_jump(struct window_mode_entry *,
     83 		    struct grid *, struct grid *, u_int, u_int, u_int, int, int,
     84 		    int, int);
     85 static int	window_copy_search(struct window_mode_entry *, int, int);
     86 static int	window_copy_search_up(struct window_mode_entry *, int);
     87 static int	window_copy_search_down(struct window_mode_entry *, int);
     88 static void	window_copy_goto_line(struct window_mode_entry *, const char *);
     89 static void	window_copy_update_cursor(struct window_mode_entry *, u_int,
     90 		    u_int);
     91 static void	window_copy_start_selection(struct window_mode_entry *);
     92 static int	window_copy_adjust_selection(struct window_mode_entry *,
     93 		    u_int *, u_int *);
     94 static int	window_copy_set_selection(struct window_mode_entry *, int, int);
     95 static int	window_copy_update_selection(struct window_mode_entry *, int,
     96 		    int);
     97 static void	window_copy_synchronize_cursor(struct window_mode_entry *, int);
     98 static void    *window_copy_get_selection(struct window_mode_entry *, size_t *);
     99 static void	window_copy_copy_buffer(struct window_mode_entry *,
    100 		    const char *, void *, size_t, int, int);
    101 static void	window_copy_pipe(struct window_mode_entry *,
    102 		    struct session *, const char *);
    103 static void	window_copy_copy_pipe(struct window_mode_entry *,
    104 		    struct session *, const char *, const char *,
    105 		    int, int);
    106 static void	window_copy_copy_selection(struct window_mode_entry *,
    107 		    const char *, int, int);
    108 static void	window_copy_append_selection(struct window_mode_entry *);
    109 static void	window_copy_clear_selection(struct window_mode_entry *);
    110 static void	window_copy_copy_line(struct window_mode_entry *, char **,
    111 		    size_t *, u_int, u_int, u_int);
    112 static int	window_copy_in_set(struct window_mode_entry *, u_int, u_int,
    113 		    const char *);
    114 static u_int	window_copy_find_length(struct window_mode_entry *, u_int);
    115 static void	window_copy_cursor_start_of_line(struct window_mode_entry *);
    116 static void	window_copy_cursor_back_to_indentation(
    117 		    struct window_mode_entry *);
    118 static void	window_copy_cursor_end_of_line(struct window_mode_entry *);
    119 static void	window_copy_other_end(struct window_mode_entry *);
    120 static void	window_copy_cursor_left(struct window_mode_entry *);
    121 static void	window_copy_cursor_right(struct window_mode_entry *, int);
    122 static void	window_copy_cursor_up(struct window_mode_entry *, int);
    123 static void	window_copy_cursor_down(struct window_mode_entry *, int);
    124 static void	window_copy_cursor_jump(struct window_mode_entry *);
    125 static void	window_copy_cursor_jump_back(struct window_mode_entry *);
    126 static void	window_copy_cursor_jump_to(struct window_mode_entry *);
    127 static void	window_copy_cursor_jump_to_back(struct window_mode_entry *);
    128 static void	window_copy_cursor_next_word(struct window_mode_entry *,
    129 		    const char *);
    130 static void	window_copy_cursor_next_word_end_pos(struct window_mode_entry *,
    131 		    const char *, u_int *, u_int *);
    132 static void	window_copy_cursor_next_word_end(struct window_mode_entry *,
    133 		    const char *, int);
    134 static void	window_copy_cursor_previous_word_pos(struct window_mode_entry *,
    135 		    const char *, u_int *, u_int *);
    136 static void	window_copy_cursor_previous_word(struct window_mode_entry *,
    137 		    const char *, int);
    138 static void	window_copy_cursor_prompt(struct window_mode_entry *, int,
    139 		    int);
    140 static void	window_copy_scroll_up(struct window_mode_entry *, u_int);
    141 static void	window_copy_scroll_down(struct window_mode_entry *, u_int);
    142 static void	window_copy_rectangle_set(struct window_mode_entry *, int);
    143 static void	window_copy_move_mouse(struct mouse_event *);
    144 static void	window_copy_drag_update(struct client *, struct mouse_event *);
    145 static void	window_copy_drag_release(struct client *, struct mouse_event *);
    146 static void	window_copy_jump_to_mark(struct window_mode_entry *);
    147 static void	window_copy_acquire_cursor_up(struct window_mode_entry *,
    148 		    u_int, u_int, u_int, u_int, u_int);
    149 static void	window_copy_acquire_cursor_down(struct window_mode_entry *,
    150 		    u_int, u_int, u_int, u_int, u_int, u_int, int);
    151 static u_int	window_copy_clip_width(u_int, u_int, u_int, u_int);
    152 static u_int	window_copy_search_mark_match(struct window_copy_mode_data *,
    153 		    u_int , u_int, u_int, int);
    154 
    155 const struct window_mode window_copy_mode = {
    156 	.name = "copy-mode",
    157 
    158 	.init = window_copy_init,
    159 	.free = window_copy_free,
    160 	.resize = window_copy_resize,
    161 	.key_table = window_copy_key_table,
    162 	.command = window_copy_command,
    163 	.formats = window_copy_formats,
    164 	.get_screen = window_copy_get_screen
    165 };
    166 
    167 const struct window_mode window_view_mode = {
    168 	.name = "view-mode",
    169 
    170 	.init = window_copy_view_init,
    171 	.free = window_copy_free,
    172 	.resize = window_copy_resize,
    173 	.key_table = window_copy_key_table,
    174 	.command = window_copy_command,
    175 	.formats = window_copy_formats,
    176 	.get_screen = window_copy_get_screen
    177 };
    178 
    179 enum {
    180 	WINDOW_COPY_OFF,
    181 	WINDOW_COPY_SEARCHUP,
    182 	WINDOW_COPY_SEARCHDOWN,
    183 	WINDOW_COPY_JUMPFORWARD,
    184 	WINDOW_COPY_JUMPBACKWARD,
    185 	WINDOW_COPY_JUMPTOFORWARD,
    186 	WINDOW_COPY_JUMPTOBACKWARD,
    187 };
    188 
    189 enum {
    190 	WINDOW_COPY_REL_POS_ABOVE,
    191 	WINDOW_COPY_REL_POS_ON_SCREEN,
    192 	WINDOW_COPY_REL_POS_BELOW,
    193 };
    194 
    195 enum window_copy_cmd_action {
    196 	WINDOW_COPY_CMD_NOTHING,
    197 	WINDOW_COPY_CMD_REDRAW,
    198 	WINDOW_COPY_CMD_CANCEL,
    199 };
    200 
    201 enum window_copy_cmd_clear {
    202 	WINDOW_COPY_CMD_CLEAR_ALWAYS,
    203 	WINDOW_COPY_CMD_CLEAR_NEVER,
    204 	WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
    205 };
    206 
    207 struct window_copy_cmd_state {
    208 	struct window_mode_entry	*wme;
    209 	struct args			*args;
    210 	struct args			*wargs;
    211 	struct mouse_event		*m;
    212 
    213 	struct client			*c;
    214 	struct session			*s;
    215 	struct winlink			*wl;
    216 };
    217 
    218 /*
    219  * Copy mode's visible screen (the "screen" field) is filled from one of two
    220  * sources: the original contents of the pane (used when we actually enter via
    221  * the "copy-mode" command, to copy the contents of the current pane), or else
    222  * a series of lines containing the output from an output-writing tmux command
    223  * (such as any of the "show-*" or "list-*" commands).
    224  *
    225  * In either case, the full content of the copy-mode grid is pointed at by the
    226  * "backing" field, and is copied into "screen" as needed (that is, when
    227  * scrolling occurs). When copy-mode is backed by a pane, backing points
    228  * directly at that pane's screen structure (&wp->base); when backed by a list
    229  * of output-lines from a command, it points at a newly-allocated screen
    230  * structure (which is deallocated when the mode ends).
    231  */
    232 struct window_copy_mode_data {
    233 	struct screen	 screen;
    234 
    235 	struct screen	*backing;
    236 	int		 backing_written; /* backing display started */
    237 	struct input_ctx *ictx;
    238 
    239 	int		 viewmode;	/* view mode entered */
    240 
    241 	u_int		 oy;		/* number of lines scrolled up */
    242 
    243 	u_int		 selx;		/* beginning of selection */
    244 	u_int		 sely;
    245 
    246 	u_int		 endselx;	/* end of selection */
    247 	u_int		 endsely;
    248 
    249 	enum {
    250 		CURSORDRAG_NONE,	/* selection is independent of cursor */
    251 		CURSORDRAG_ENDSEL,	/* end is synchronized with cursor */
    252 		CURSORDRAG_SEL,		/* start is synchronized with cursor */
    253 	} cursordrag;
    254 
    255 	int		 modekeys;
    256 	enum {
    257 		LINE_SEL_NONE,
    258 		LINE_SEL_LEFT_RIGHT,
    259 		LINE_SEL_RIGHT_LEFT,
    260 	} lineflag;			/* line selection mode */
    261 	int		 rectflag;	/* in rectangle copy mode? */
    262 	int		 scroll_exit;	/* exit on scroll to end? */
    263 	int		 hide_position;	/* hide position marker */
    264 
    265 	enum {
    266 		SEL_CHAR,		/* select one char at a time */
    267 		SEL_WORD,		/* select one word at a time */
    268 		SEL_LINE,		/* select one line at a time */
    269 	} selflag;
    270 
    271 	const char	*separators;	/* word separators */
    272 
    273 	u_int		 dx;		/* drag start position */
    274 	u_int		 dy;
    275 
    276 	u_int		 selrx;		/* selection reset positions */
    277 	u_int		 selry;
    278 	u_int		 endselrx;
    279 	u_int		 endselry;
    280 
    281 	u_int		 cx;
    282 	u_int		 cy;
    283 
    284 	u_int		 lastcx; 	/* position in last line w/ content */
    285 	u_int		 lastsx;	/* size of last line w/ content */
    286 
    287 	u_int		 mx;		/* mark position */
    288 	u_int		 my;
    289 	int		 showmark;
    290 
    291 	int		 searchtype;
    292 	int		 searchdirection;
    293 	int		 searchregex;
    294 	char		*searchstr;
    295 	u_char		*searchmark;
    296 	int		 searchcount;
    297 	int		 searchmore;
    298 	int		 searchall;
    299 	int		 searchx;
    300 	int		 searchy;
    301 	int		 searcho;
    302 	u_char		 searchgen;
    303 
    304 	int		 timeout;	/* search has timed out */
    305 #define WINDOW_COPY_SEARCH_TIMEOUT 10000
    306 #define WINDOW_COPY_SEARCH_ALL_TIMEOUT 200
    307 #define WINDOW_COPY_SEARCH_MAX_LINE 2000
    308 
    309 	int			 jumptype;
    310 	struct utf8_data	*jumpchar;
    311 
    312 	struct event	 dragtimer;
    313 #define WINDOW_COPY_DRAG_REPEAT_TIME 50000
    314 };
    315 
    316 static void
    317 window_copy_scroll_timer(__unused int fd, __unused short events, void *arg)
    318 {
    319 	struct window_mode_entry	*wme = arg;
    320 	struct window_pane		*wp = wme->wp;
    321 	struct window_copy_mode_data	*data = wme->data;
    322 	struct timeval			 tv = {
    323 		.tv_usec = WINDOW_COPY_DRAG_REPEAT_TIME
    324 	};
    325 
    326 	evtimer_del(&data->dragtimer);
    327 
    328 	if (TAILQ_FIRST(&wp->modes) != wme)
    329 		return;
    330 
    331 	if (data->cy == 0) {
    332 		evtimer_add(&data->dragtimer, &tv);
    333 		window_copy_cursor_up(wme, 1);
    334 	} else if (data->cy == screen_size_y(&data->screen) - 1) {
    335 		evtimer_add(&data->dragtimer, &tv);
    336 		window_copy_cursor_down(wme, 1);
    337 	}
    338 }
    339 
    340 static struct screen *
    341 window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
    342     u_int *cy, int trim)
    343 {
    344 	struct screen		*dst;
    345 	const struct grid_line	*gl;
    346 	u_int			 sy, wx, wy;
    347 	int			 reflow;
    348 
    349 	dst = xcalloc(1, sizeof *dst);
    350 
    351 	sy = screen_hsize(src) + screen_size_y(src);
    352 	if (trim) {
    353 		while (sy > screen_hsize(src)) {
    354 			gl = grid_peek_line(src->grid, sy - 1);
    355 			if (gl->cellused != 0)
    356 				break;
    357 			sy--;
    358 		}
    359 	}
    360 	log_debug("%s: target screen is %ux%u, source %ux%u", __func__,
    361 	    screen_size_x(src), sy, screen_size_x(hint),
    362 	    screen_hsize(src) + screen_size_y(src));
    363 	screen_init(dst, screen_size_x(src), sy, screen_hlimit(src));
    364 
    365 	/*
    366 	 * Ensure history is on for the backing grid so lines are not deleted
    367 	 * during resizing.
    368 	 */
    369 	dst->grid->flags |= GRID_HISTORY;
    370 	grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy);
    371 
    372 	dst->grid->sy = sy - screen_hsize(src);
    373 	dst->grid->hsize = screen_hsize(src);
    374 	dst->grid->hscrolled = src->grid->hscrolled;
    375 	if (src->cy > dst->grid->sy - 1) {
    376 		dst->cx = 0;
    377 		dst->cy = dst->grid->sy - 1;
    378 	} else {
    379 		dst->cx = src->cx;
    380 		dst->cy = src->cy;
    381 	}
    382 
    383 	if (cx != NULL && cy != NULL) {
    384 		*cx = dst->cx;
    385 		*cy = screen_hsize(dst) + dst->cy;
    386 		reflow = (screen_size_x(hint) != screen_size_x(dst));
    387 	}
    388 	else
    389 		reflow = 0;
    390 	if (reflow)
    391 		grid_wrap_position(dst->grid, *cx, *cy, &wx, &wy);
    392 	screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1,
    393 	    0, 0);
    394 	if (reflow)
    395 		grid_unwrap_position(dst->grid, cx, cy, wx, wy);
    396 
    397 	return (dst);
    398 }
    399 
    400 static struct window_copy_mode_data *
    401 window_copy_common_init(struct window_mode_entry *wme)
    402 {
    403 	struct window_pane		*wp = wme->wp;
    404 	struct window_copy_mode_data	*data;
    405 	struct screen			*base = &wp->base;
    406 
    407 	wme->data = data = xcalloc(1, sizeof *data);
    408 
    409 	data->cursordrag = CURSORDRAG_NONE;
    410 	data->lineflag = LINE_SEL_NONE;
    411 	data->selflag = SEL_CHAR;
    412 
    413 	if (wp->searchstr != NULL) {
    414 		data->searchtype = WINDOW_COPY_SEARCHUP;
    415 		data->searchregex = wp->searchregex;
    416 		data->searchstr = xstrdup(wp->searchstr);
    417 	} else {
    418 		data->searchtype = WINDOW_COPY_OFF;
    419 		data->searchregex = 0;
    420 		data->searchstr = NULL;
    421 	}
    422 	data->searchx = data->searchy = data->searcho = -1;
    423 	data->searchall = 1;
    424 
    425 	data->jumptype = WINDOW_COPY_OFF;
    426 	data->jumpchar = NULL;
    427 
    428 	screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0);
    429 	screen_set_default_cursor(&data->screen, global_w_options);
    430 	data->modekeys = options_get_number(wp->window->options, "mode-keys");
    431 
    432 	evtimer_set(&data->dragtimer, window_copy_scroll_timer, wme);
    433 
    434 	return (data);
    435 }
    436 
    437 static struct screen *
    438 window_copy_init(struct window_mode_entry *wme,
    439     __unused struct cmd_find_state *fs, struct args *args)
    440 {
    441 	struct window_pane		*wp = wme->swp;
    442 	struct window_copy_mode_data	*data;
    443 	struct screen			*base = &wp->base;
    444 	struct screen_write_ctx		 ctx;
    445 	u_int				 i, cx, cy;
    446 
    447 	data = window_copy_common_init(wme);
    448 	data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy,
    449 	    wme->swp != wme->wp);
    450 
    451 	data->cx = cx;
    452 	if (cy < screen_hsize(data->backing)) {
    453 		data->cy = 0;
    454 		data->oy = screen_hsize(data->backing) - cy;
    455 	} else {
    456 		data->cy = cy - screen_hsize(data->backing);
    457 		data->oy = 0;
    458 	}
    459 
    460 	data->scroll_exit = args_has(args, 'e');
    461 	data->hide_position = args_has(args, 'H');
    462 
    463 	if (base->hyperlinks != NULL)
    464 		data->screen.hyperlinks = hyperlinks_copy(base->hyperlinks);
    465 	data->screen.cx = data->cx;
    466 	data->screen.cy = data->cy;
    467 	data->mx = data->cx;
    468 	data->my = screen_hsize(data->backing) + data->cy - data->oy;
    469 	data->showmark = 0;
    470 
    471 	screen_write_start(&ctx, &data->screen);
    472 	for (i = 0; i < screen_size_y(&data->screen); i++)
    473 		window_copy_write_line(wme, &ctx, i);
    474 	screen_write_cursormove(&ctx, data->cx, data->cy, 0);
    475 	screen_write_stop(&ctx);
    476 
    477 	return (&data->screen);
    478 }
    479 
    480 static struct screen *
    481 window_copy_view_init(struct window_mode_entry *wme,
    482     __unused struct cmd_find_state *fs, __unused struct args *args)
    483 {
    484 	struct window_pane		*wp = wme->wp;
    485 	struct window_copy_mode_data	*data;
    486 	struct screen			*base = &wp->base;
    487 	u_int				 sx = screen_size_x(base);
    488 
    489 	data = window_copy_common_init(wme);
    490 	data->viewmode = 1;
    491 
    492 	data->backing = xmalloc(sizeof *data->backing);
    493 	screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
    494 	data->ictx = input_init(NULL, NULL, NULL);
    495 	data->mx = data->cx;
    496 	data->my = screen_hsize(data->backing) + data->cy - data->oy;
    497 	data->showmark = 0;
    498 
    499 	return (&data->screen);
    500 }
    501 
    502 static void
    503 window_copy_free(struct window_mode_entry *wme)
    504 {
    505 	struct window_copy_mode_data	*data = wme->data;
    506 
    507 	evtimer_del(&data->dragtimer);
    508 
    509 	free(data->searchmark);
    510 	free(data->searchstr);
    511 	free(data->jumpchar);
    512 
    513 	if (data->ictx != NULL)
    514 		input_free(data->ictx);
    515 	screen_free(data->backing);
    516 	free(data->backing);
    517 
    518 	screen_free(&data->screen);
    519 	free(data);
    520 }
    521 
    522 void
    523 window_copy_add(struct window_pane *wp, int parse, const char *fmt, ...)
    524 {
    525 	va_list	ap;
    526 
    527 	va_start(ap, fmt);
    528 	window_copy_vadd(wp, parse, fmt, ap);
    529 	va_end(ap);
    530 }
    531 
    532 static void
    533 window_copy_init_ctx_cb(__unused struct screen_write_ctx *ctx,
    534     struct tty_ctx *ttyctx)
    535 {
    536 	memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults);
    537 	ttyctx->palette = NULL;
    538 	ttyctx->redraw_cb = NULL;
    539 	ttyctx->set_client_cb = NULL;
    540 	ttyctx->arg = NULL;
    541 }
    542 
    543 void
    544 window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap)
    545 {
    546 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    547 	struct window_copy_mode_data	*data = wme->data;
    548 	struct screen			*backing = data->backing;
    549 	struct screen_write_ctx	 	 backing_ctx, ctx;
    550 	struct grid_cell		 gc;
    551 	u_int				 old_hsize, old_cy;
    552 	char				*text;
    553 
    554 	old_hsize = screen_hsize(data->backing);
    555 	screen_write_start(&backing_ctx, backing);
    556 	if (data->backing_written) {
    557 		/*
    558 		 * On the second or later line, do a CRLF before writing
    559 		 * (so it's on a new line).
    560 		 */
    561 		screen_write_carriagereturn(&backing_ctx);
    562 		screen_write_linefeed(&backing_ctx, 0, 8);
    563 	} else
    564 		data->backing_written = 1;
    565 	old_cy = backing->cy;
    566 	if (parse) {
    567 		vasprintf(&text, fmt, ap);
    568 		input_parse_screen(data->ictx, backing, window_copy_init_ctx_cb,
    569 		    data, text, strlen(text));
    570 		free(text);
    571 	} else {
    572 		memcpy(&gc, &grid_default_cell, sizeof gc);
    573 		screen_write_vnputs(&backing_ctx, 0, &gc, fmt, ap);
    574 	}
    575 	screen_write_stop(&backing_ctx);
    576 
    577 	data->oy += screen_hsize(data->backing) - old_hsize;
    578 
    579 	screen_write_start_pane(&ctx, wp, &data->screen);
    580 
    581 	/*
    582 	 * If the history has changed, draw the top line.
    583 	 * (If there's any history at all, it has changed.)
    584 	 */
    585 	if (screen_hsize(data->backing))
    586 		window_copy_redraw_lines(wme, 0, 1);
    587 
    588 	/* Write the new lines. */
    589 	window_copy_redraw_lines(wme, old_cy, backing->cy - old_cy + 1);
    590 
    591 	screen_write_stop(&ctx);
    592 }
    593 
    594 void
    595 window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my,
    596     int scroll_exit)
    597 {
    598 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    599 
    600 	if (wme != NULL) {
    601 		window_set_active_pane(wp->window, wp, 0);
    602 		window_copy_scroll1(wme, wp, sl_mpos, my, scroll_exit);
    603 	}
    604 }
    605 
    606 static void
    607 window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
    608     int sl_mpos, u_int my, int scroll_exit)
    609 {
    610 	struct window_copy_mode_data	*data = wme->data;
    611 	u_int				 ox, oy, px, py, n, offset, size;
    612 	u_int				 new_offset;
    613 	u_int				 slider_height = wp->sb_slider_h;
    614 	u_int				 sb_height = wp->sy, sb_top = wp->yoff;
    615 	u_int				 sy = screen_size_y(data->backing);
    616 	int				 new_slider_y, delta;
    617 
    618 	/*
    619 	 * sl_mpos is where in the slider the user is dragging, mouse is
    620 	 * dragging this y point relative to top of slider.
    621 	 */
    622 	if (my <= sb_top + sl_mpos) {
    623 		/* Slider banged into top. */
    624 		new_slider_y = sb_top - wp->yoff;
    625 	} else if (my - sl_mpos > sb_top + sb_height - slider_height) {
    626 		/* Slider banged into bottom. */
    627 		new_slider_y = sb_top - wp->yoff + (sb_height - slider_height);
    628 	} else {
    629 		/* Slider is somewhere in the middle. */
    630 		new_slider_y = my - wp->yoff - sl_mpos;
    631 	}
    632 
    633 	if (TAILQ_FIRST(&wp->modes) == NULL ||
    634 	    window_copy_get_current_offset(wp, &offset, &size) == 0)
    635 		return;
    636 
    637 	/*
    638 	 * See screen_redraw_draw_pane_scrollbar - this is the inverse of the
    639 	 * formula used there.
    640 	 */
    641 	new_offset = new_slider_y * ((float)(size + sb_height) / sb_height);
    642 	delta = (int)offset - new_offset;
    643 
    644 	/*
    645 	 * Move pane view around based on delta relative to the cursor,
    646 	 * maintaining the selection.
    647 	 */
    648 	oy = screen_hsize(data->backing) + data->cy - data->oy;
    649 	ox = window_copy_find_length(wme, oy);
    650 
    651 	if (data->cx != ox) {
    652 		data->lastcx = data->cx;
    653 		data->lastsx = ox;
    654 	}
    655 	data->cx = data->lastcx;
    656 
    657 	if (delta >= 0) {
    658 		n = (u_int)delta;
    659 		if (data->oy + n > screen_hsize(data->backing)) {
    660 			data->oy = screen_hsize(data->backing);
    661 			if (data->cy < n)
    662 				data->cy = 0;
    663 			else
    664 				data->cy -= n;
    665 		} else
    666 			data->oy += n;
    667 	} else {
    668 		n = (u_int)-delta;
    669 		if (data->oy < n) {
    670 			data->oy = 0;
    671 			if (data->cy + (n - data->oy) >= sy)
    672 				data->cy = sy - 1;
    673 			else
    674 				data->cy += n - data->oy;
    675 		} else
    676 			data->oy -= n;
    677 	}
    678 
    679 	/* Don't also drag tail when dragging a scrollbar, it looks weird. */
    680 	data->cursordrag = CURSORDRAG_NONE;
    681 
    682 	if (data->screen.sel == NULL || !data->rectflag) {
    683 		py = screen_hsize(data->backing) + data->cy - data->oy;
    684 		px = window_copy_find_length(wme, py);
    685 		if ((data->cx >= data->lastsx && data->cx != px) ||
    686 		    data->cx > px)
    687 			window_copy_cursor_end_of_line(wme);
    688 	}
    689 
    690 	if (scroll_exit && data->oy == 0) {
    691 		window_pane_reset_mode(wp);
    692 		return;
    693 	}
    694 
    695 	if (data->searchmark != NULL && !data->timeout)
    696 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
    697 	window_copy_update_selection(wme, 1, 0);
    698 	window_copy_redraw_screen(wme);
    699 }
    700 
    701 void
    702 window_copy_pageup(struct window_pane *wp, int half_page)
    703 {
    704 	window_copy_pageup1(TAILQ_FIRST(&wp->modes), half_page);
    705 }
    706 
    707 static void
    708 window_copy_pageup1(struct window_mode_entry *wme, int half_page)
    709 {
    710 	struct window_copy_mode_data	*data = wme->data;
    711 	struct screen			*s = &data->screen;
    712 	u_int				 n, ox, oy, px, py;
    713 
    714 	oy = screen_hsize(data->backing) + data->cy - data->oy;
    715 	ox = window_copy_find_length(wme, oy);
    716 
    717 	if (data->cx != ox) {
    718 		data->lastcx = data->cx;
    719 		data->lastsx = ox;
    720 	}
    721 	data->cx = data->lastcx;
    722 
    723 	n = 1;
    724 	if (screen_size_y(s) > 2) {
    725 		if (half_page)
    726 			n = screen_size_y(s) / 2;
    727 		else
    728 			n = screen_size_y(s) - 2;
    729 	}
    730 
    731 	if (data->oy + n > screen_hsize(data->backing)) {
    732 		data->oy = screen_hsize(data->backing);
    733 		if (data->cy < n)
    734 			data->cy = 0;
    735 		else
    736 			data->cy -= n;
    737 	} else
    738 		data->oy += n;
    739 
    740 	if (data->screen.sel == NULL || !data->rectflag) {
    741 		py = screen_hsize(data->backing) + data->cy - data->oy;
    742 		px = window_copy_find_length(wme, py);
    743 		if ((data->cx >= data->lastsx && data->cx != px) ||
    744 		    data->cx > px)
    745 			window_copy_cursor_end_of_line(wme);
    746 	}
    747 
    748 	if (data->searchmark != NULL && !data->timeout)
    749 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
    750 	window_copy_update_selection(wme, 1, 0);
    751 	window_copy_redraw_screen(wme);
    752 }
    753 
    754 void
    755 window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit)
    756 {
    757 	if (window_copy_pagedown1(TAILQ_FIRST(&wp->modes), half_page,
    758 	    scroll_exit)) {
    759 		window_pane_reset_mode(wp);
    760 		return;
    761 	}
    762 }
    763 
    764 static int
    765 window_copy_pagedown1(struct window_mode_entry *wme, int half_page,
    766     int scroll_exit)
    767 {
    768 	struct window_copy_mode_data	*data = wme->data;
    769 	struct screen			*s = &data->screen;
    770 	u_int				 n, ox, oy, px, py;
    771 
    772 	oy = screen_hsize(data->backing) + data->cy - data->oy;
    773 	ox = window_copy_find_length(wme, oy);
    774 
    775 	if (data->cx != ox) {
    776 		data->lastcx = data->cx;
    777 		data->lastsx = ox;
    778 	}
    779 	data->cx = data->lastcx;
    780 
    781 	n = 1;
    782 	if (screen_size_y(s) > 2) {
    783 		if (half_page)
    784 			n = screen_size_y(s) / 2;
    785 		else
    786 			n = screen_size_y(s) - 2;
    787 	}
    788 
    789 	if (data->oy < n) {
    790 		data->oy = 0;
    791 		if (data->cy + (n - data->oy) >= screen_size_y(data->backing))
    792 			data->cy = screen_size_y(data->backing) - 1;
    793 		else
    794 			data->cy += n - data->oy;
    795 	} else
    796 		data->oy -= n;
    797 
    798 	if (data->screen.sel == NULL || !data->rectflag) {
    799 		py = screen_hsize(data->backing) + data->cy - data->oy;
    800 		px = window_copy_find_length(wme, py);
    801 		if ((data->cx >= data->lastsx && data->cx != px) ||
    802 		    data->cx > px)
    803 			window_copy_cursor_end_of_line(wme);
    804 	}
    805 
    806 	if (scroll_exit && data->oy == 0)
    807 		return (1);
    808 	if (data->searchmark != NULL && !data->timeout)
    809 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
    810 	window_copy_update_selection(wme, 1, 0);
    811 	window_copy_redraw_screen(wme);
    812 	return (0);
    813 }
    814 
    815 static void
    816 window_copy_previous_paragraph(struct window_mode_entry *wme)
    817 {
    818 	struct window_copy_mode_data	*data = wme->data;
    819 	u_int				 oy;
    820 
    821 	oy = screen_hsize(data->backing) + data->cy - data->oy;
    822 
    823 	while (oy > 0 && window_copy_find_length(wme, oy) == 0)
    824 		oy--;
    825 
    826 	while (oy > 0 && window_copy_find_length(wme, oy) > 0)
    827 		oy--;
    828 
    829 	window_copy_scroll_to(wme, 0, oy, 0);
    830 }
    831 
    832 static void
    833 window_copy_next_paragraph(struct window_mode_entry *wme)
    834 {
    835 	struct window_copy_mode_data	*data = wme->data;
    836 	struct screen			*s = &data->screen;
    837 	u_int				 maxy, ox, oy;
    838 
    839 	oy = screen_hsize(data->backing) + data->cy - data->oy;
    840 	maxy = screen_hsize(data->backing) + screen_size_y(s) - 1;
    841 
    842 	while (oy < maxy && window_copy_find_length(wme, oy) == 0)
    843 		oy++;
    844 
    845 	while (oy < maxy && window_copy_find_length(wme, oy) > 0)
    846 		oy++;
    847 
    848 	ox = window_copy_find_length(wme, oy);
    849 	window_copy_scroll_to(wme, ox, oy, 0);
    850 }
    851 
    852 char *
    853 window_copy_get_word(struct window_pane *wp, u_int x, u_int y)
    854 {
    855 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    856 	struct window_copy_mode_data	*data = wme->data;
    857 	struct grid			*gd = data->backing->grid;
    858 
    859 	return (format_grid_word(gd, x, gd->hsize + y - data->oy));
    860 }
    861 
    862 char *
    863 window_copy_get_line(struct window_pane *wp, u_int y)
    864 {
    865 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    866 	struct window_copy_mode_data	*data = wme->data;
    867 	struct grid			*gd = data->screen.grid;
    868 
    869 	return (format_grid_line(gd, gd->hsize + y));
    870 }
    871 
    872 char *
    873 window_copy_get_hyperlink(struct window_pane *wp, u_int x, u_int y)
    874 {
    875 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    876 	struct window_copy_mode_data	*data = wme->data;
    877 	struct grid			*gd = data->screen.grid;
    878 
    879 	return (format_grid_hyperlink(gd, x, gd->hsize + y, wp->screen));
    880 }
    881 
    882 static void *
    883 window_copy_cursor_hyperlink_cb(struct format_tree *ft)
    884 {
    885 	struct window_pane		*wp = format_get_pane(ft);
    886 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    887 	struct window_copy_mode_data	*data = wme->data;
    888 	struct grid			*gd = data->screen.grid;
    889 
    890 	return (format_grid_hyperlink(gd, data->cx, gd->hsize + data->cy,
    891 	    &data->screen));
    892 }
    893 
    894 static void *
    895 window_copy_cursor_word_cb(struct format_tree *ft)
    896 {
    897 	struct window_pane		*wp = format_get_pane(ft);
    898 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    899 	struct window_copy_mode_data	*data = wme->data;
    900 
    901 	return (window_copy_get_word(wp, data->cx, data->cy));
    902 }
    903 
    904 static void *
    905 window_copy_cursor_line_cb(struct format_tree *ft)
    906 {
    907 	struct window_pane		*wp = format_get_pane(ft);
    908 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    909 	struct window_copy_mode_data	*data = wme->data;
    910 
    911 	return (window_copy_get_line(wp, data->cy));
    912 }
    913 
    914 static void *
    915 window_copy_search_match_cb(struct format_tree *ft)
    916 {
    917 	struct window_pane		*wp = format_get_pane(ft);
    918 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
    919 	struct window_copy_mode_data	*data = wme->data;
    920 
    921 	return (window_copy_match_at_cursor(data));
    922 }
    923 
    924 static void
    925 window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
    926 {
    927 	struct window_copy_mode_data	*data = wme->data;
    928 	u_int				 hsize = screen_hsize(data->backing);
    929 	struct grid_line		*gl;
    930 
    931 	gl = grid_get_line(data->backing->grid, hsize - data->oy);
    932 	format_add(ft, "top_line_time", "%llu", (unsigned long long)gl->time);
    933 
    934 	format_add(ft, "scroll_position", "%d", data->oy);
    935 	format_add(ft, "rectangle_toggle", "%d", data->rectflag);
    936 
    937 	format_add(ft, "copy_cursor_x", "%d", data->cx);
    938 	format_add(ft, "copy_cursor_y", "%d", data->cy);
    939 
    940 	if (data->screen.sel != NULL) {
    941 		format_add(ft, "selection_start_x", "%d", data->selx);
    942 		format_add(ft, "selection_start_y", "%d", data->sely);
    943 		format_add(ft, "selection_end_x", "%d", data->endselx);
    944 		format_add(ft, "selection_end_y", "%d", data->endsely);
    945 
    946 		if (data->cursordrag != CURSORDRAG_NONE)
    947 			format_add(ft, "selection_active", "1");
    948 		else
    949 			format_add(ft, "selection_active", "0");
    950 		if (data->endselx != data->selx || data->endsely != data->sely)
    951 			format_add(ft, "selection_present", "1");
    952 		else
    953 			format_add(ft, "selection_present", "0");
    954 	} else {
    955 		format_add(ft, "selection_active", "0");
    956 		format_add(ft, "selection_present", "0");
    957 	}
    958 
    959 	format_add(ft, "search_present", "%d", data->searchmark != NULL);
    960 	format_add(ft, "search_timed_out", "%d", data->timeout);
    961 	if (data->searchcount != -1) {
    962 		format_add(ft, "search_count", "%d", data->searchcount);
    963 		format_add(ft, "search_count_partial", "%d", data->searchmore);
    964 	}
    965 	format_add_cb(ft, "search_match", window_copy_search_match_cb);
    966 
    967 	format_add_cb(ft, "copy_cursor_word", window_copy_cursor_word_cb);
    968 	format_add_cb(ft, "copy_cursor_line", window_copy_cursor_line_cb);
    969 	format_add_cb(ft, "copy_cursor_hyperlink",
    970 	    window_copy_cursor_hyperlink_cb);
    971 }
    972 
    973 static struct screen *
    974 window_copy_get_screen(struct window_mode_entry *wme)
    975 {
    976 	struct window_copy_mode_data	*data = wme->data;
    977 
    978 	return (data->backing);
    979 }
    980 
    981 static void
    982 window_copy_size_changed(struct window_mode_entry *wme)
    983 {
    984 	struct window_copy_mode_data	*data = wme->data;
    985 	struct screen			*s = &data->screen;
    986 	struct screen_write_ctx		 ctx;
    987 	int				 search = (data->searchmark != NULL);
    988 
    989 	window_copy_clear_selection(wme);
    990 	window_copy_clear_marks(wme);
    991 
    992 	screen_write_start(&ctx, s);
    993 	window_copy_write_lines(wme, &ctx, 0, screen_size_y(s));
    994 	screen_write_stop(&ctx);
    995 
    996 	if (search && !data->timeout)
    997 		window_copy_search_marks(wme, NULL, data->searchregex, 0);
    998 	data->searchx = data->cx;
    999 	data->searchy = data->cy;
   1000 	data->searcho = data->oy;
   1001 }
   1002 
   1003 static void
   1004 window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
   1005 {
   1006 	struct window_copy_mode_data	*data = wme->data;
   1007 	struct screen			*s = &data->screen;
   1008 	struct grid			*gd = data->backing->grid;
   1009 	u_int				 cx, cy, wx, wy;
   1010 	int				 reflow;
   1011 
   1012 	screen_resize(s, sx, sy, 0);
   1013 	cx = data->cx;
   1014 	cy = gd->hsize + data->cy - data->oy;
   1015 	reflow = (gd->sx != sx);
   1016 	if (reflow)
   1017 		grid_wrap_position(gd, cx, cy, &wx, &wy);
   1018 	screen_resize_cursor(data->backing, sx, sy, 1, 0, 0);
   1019 	if (reflow)
   1020 		grid_unwrap_position(gd, &cx, &cy, wx, wy);
   1021 
   1022 	data->cx = cx;
   1023 	if (cy < gd->hsize) {
   1024 		data->cy = 0;
   1025 		data->oy = gd->hsize - cy;
   1026 	} else {
   1027 		data->cy = cy - gd->hsize;
   1028 		data->oy = 0;
   1029 	}
   1030 
   1031 	window_copy_size_changed(wme);
   1032 	window_copy_redraw_screen(wme);
   1033 }
   1034 
   1035 static const char *
   1036 window_copy_key_table(struct window_mode_entry *wme)
   1037 {
   1038 	struct window_pane	*wp = wme->wp;
   1039 
   1040 	if (options_get_number(wp->window->options, "mode-keys") == MODEKEY_VI)
   1041 		return ("copy-mode-vi");
   1042 	return ("copy-mode");
   1043 }
   1044 
   1045 static int
   1046 window_copy_expand_search_string(struct window_copy_cmd_state *cs)
   1047 {
   1048 	struct window_mode_entry	*wme = cs->wme;
   1049 	struct window_copy_mode_data	*data = wme->data;
   1050 	const char			*ss = args_string(cs->wargs, 0);
   1051 	char				*expanded;
   1052 
   1053 	if (ss == NULL || *ss == '\0')
   1054 		return (0);
   1055 
   1056 	if (args_has(cs->args, 'F')) {
   1057 		expanded = format_single(NULL, ss, NULL, NULL, NULL, wme->wp);
   1058 		if (*expanded == '\0') {
   1059 			free(expanded);
   1060 			return (0);
   1061 		}
   1062 		free(data->searchstr);
   1063 		data->searchstr = expanded;
   1064 	} else {
   1065 		free(data->searchstr);
   1066 		data->searchstr = xstrdup(ss);
   1067 	}
   1068 	return (1);
   1069 }
   1070 
   1071 static enum window_copy_cmd_action
   1072 window_copy_cmd_append_selection(struct window_copy_cmd_state *cs)
   1073 {
   1074 	struct window_mode_entry	*wme = cs->wme;
   1075 	struct session			*s = cs->s;
   1076 
   1077 	if (s != NULL)
   1078 		window_copy_append_selection(wme);
   1079 	window_copy_clear_selection(wme);
   1080 	return (WINDOW_COPY_CMD_REDRAW);
   1081 }
   1082 
   1083 static enum window_copy_cmd_action
   1084 window_copy_cmd_append_selection_and_cancel(struct window_copy_cmd_state *cs)
   1085 {
   1086 	struct window_mode_entry	*wme = cs->wme;
   1087 	struct session			*s = cs->s;
   1088 
   1089 	if (s != NULL)
   1090 		window_copy_append_selection(wme);
   1091 	window_copy_clear_selection(wme);
   1092 	return (WINDOW_COPY_CMD_CANCEL);
   1093 }
   1094 
   1095 static enum window_copy_cmd_action
   1096 window_copy_cmd_back_to_indentation(struct window_copy_cmd_state *cs)
   1097 {
   1098 	struct window_mode_entry	*wme = cs->wme;
   1099 
   1100 	window_copy_cursor_back_to_indentation(wme);
   1101 	return (WINDOW_COPY_CMD_NOTHING);
   1102 }
   1103 
   1104 static enum window_copy_cmd_action
   1105 window_copy_cmd_begin_selection(struct window_copy_cmd_state *cs)
   1106 {
   1107 	struct window_mode_entry	*wme = cs->wme;
   1108 	struct client			*c = cs->c;
   1109 	struct mouse_event		*m = cs->m;
   1110 	struct window_copy_mode_data	*data = wme->data;
   1111 
   1112 	if (m != NULL) {
   1113 		window_copy_start_drag(c, m);
   1114 		return (WINDOW_COPY_CMD_NOTHING);
   1115 	}
   1116 
   1117 	data->lineflag = LINE_SEL_NONE;
   1118 	data->selflag = SEL_CHAR;
   1119 	window_copy_start_selection(wme);
   1120 	return (WINDOW_COPY_CMD_REDRAW);
   1121 }
   1122 
   1123 static enum window_copy_cmd_action
   1124 window_copy_cmd_stop_selection(struct window_copy_cmd_state *cs)
   1125 {
   1126 	struct window_mode_entry	*wme = cs->wme;
   1127 	struct window_copy_mode_data	*data = wme->data;
   1128 
   1129 	data->cursordrag = CURSORDRAG_NONE;
   1130 	data->lineflag = LINE_SEL_NONE;
   1131 	data->selflag = SEL_CHAR;
   1132 	return (WINDOW_COPY_CMD_NOTHING);
   1133 }
   1134 
   1135 static enum window_copy_cmd_action
   1136 window_copy_cmd_bottom_line(struct window_copy_cmd_state *cs)
   1137 {
   1138 	struct window_mode_entry	*wme = cs->wme;
   1139 	struct window_copy_mode_data	*data = wme->data;
   1140 
   1141 	data->cx = 0;
   1142 	data->cy = screen_size_y(&data->screen) - 1;
   1143 
   1144 	window_copy_update_selection(wme, 1, 0);
   1145 	return (WINDOW_COPY_CMD_REDRAW);
   1146 }
   1147 
   1148 static enum window_copy_cmd_action
   1149 window_copy_cmd_cancel(__unused struct window_copy_cmd_state *cs)
   1150 {
   1151 	return (WINDOW_COPY_CMD_CANCEL);
   1152 }
   1153 
   1154 static enum window_copy_cmd_action
   1155 window_copy_cmd_clear_selection(struct window_copy_cmd_state *cs)
   1156 {
   1157 	struct window_mode_entry	*wme = cs->wme;
   1158 
   1159 	window_copy_clear_selection(wme);
   1160 	return (WINDOW_COPY_CMD_REDRAW);
   1161 }
   1162 
   1163 static enum window_copy_cmd_action
   1164 window_copy_do_copy_end_of_line(struct window_copy_cmd_state *cs, int pipe,
   1165     int cancel)
   1166 {
   1167 	struct window_mode_entry	 *wme = cs->wme;
   1168 	struct client			 *c = cs->c;
   1169 	struct session			 *s = cs->s;
   1170 	struct winlink			 *wl = cs->wl;
   1171 	struct window_pane		 *wp = wme->wp;
   1172 	u_int				  count = args_count(cs->wargs);
   1173 	u_int				  np = wme->prefix, ocx, ocy, ooy;
   1174 	struct window_copy_mode_data	 *data = wme->data;
   1175 	char				 *prefix = NULL, *command = NULL;
   1176 	const char			 *arg0 = args_string(cs->wargs, 0);
   1177 	const char			 *arg1 = args_string(cs->wargs, 1);
   1178 	int				  set_paste = !args_has(cs->wargs, 'P');
   1179 	int				  set_clip = !args_has(cs->wargs, 'C');
   1180 
   1181 	if (pipe) {
   1182 		if (count == 2)
   1183 			prefix = format_single(NULL, arg1, c, s, wl, wp);
   1184 		if (s != NULL && count > 0 && *arg0 != '\0')
   1185 			command = format_single(NULL, arg0, c, s, wl, wp);
   1186 	} else {
   1187 		if (count == 1)
   1188 			prefix = format_single(NULL, arg0, c, s, wl, wp);
   1189 	}
   1190 
   1191 	ocx = data->cx;
   1192 	ocy = data->cy;
   1193 	ooy = data->oy;
   1194 
   1195 	window_copy_start_selection(wme);
   1196 	for (; np > 1; np--)
   1197 		window_copy_cursor_down(wme, 0);
   1198 	window_copy_cursor_end_of_line(wme);
   1199 
   1200 	if (s != NULL) {
   1201 		if (pipe)
   1202 			window_copy_copy_pipe(wme, s, prefix, command,
   1203 			    set_paste, set_clip);
   1204 		else
   1205 			window_copy_copy_selection(wme, prefix,
   1206 			    set_paste, set_clip);
   1207 
   1208 		if (cancel) {
   1209 			free(prefix);
   1210 			free(command);
   1211 			return (WINDOW_COPY_CMD_CANCEL);
   1212 		}
   1213 	}
   1214 	window_copy_clear_selection(wme);
   1215 
   1216 	data->cx = ocx;
   1217 	data->cy = ocy;
   1218 	data->oy = ooy;
   1219 
   1220 	free(prefix);
   1221 	free(command);
   1222 	return (WINDOW_COPY_CMD_REDRAW);
   1223 }
   1224 
   1225 static enum window_copy_cmd_action
   1226 window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs)
   1227 {
   1228 	return (window_copy_do_copy_end_of_line(cs, 0, 0));
   1229 }
   1230 
   1231 static enum window_copy_cmd_action
   1232 window_copy_cmd_copy_end_of_line_and_cancel(struct window_copy_cmd_state *cs)
   1233 {
   1234 	return (window_copy_do_copy_end_of_line(cs, 0, 1));
   1235 }
   1236 
   1237 static enum window_copy_cmd_action
   1238 window_copy_cmd_copy_pipe_end_of_line(struct window_copy_cmd_state *cs)
   1239 {
   1240 	return (window_copy_do_copy_end_of_line(cs, 1, 0));
   1241 }
   1242 
   1243 static enum window_copy_cmd_action
   1244 window_copy_cmd_copy_pipe_end_of_line_and_cancel(
   1245     struct window_copy_cmd_state *cs)
   1246 {
   1247 	return (window_copy_do_copy_end_of_line(cs, 1, 1));
   1248 }
   1249 
   1250 static enum window_copy_cmd_action
   1251 window_copy_do_copy_line(struct window_copy_cmd_state *cs, int pipe, int cancel)
   1252 {
   1253 	struct window_mode_entry	 *wme = cs->wme;
   1254 	struct client			 *c = cs->c;
   1255 	struct session			 *s = cs->s;
   1256 	struct winlink			 *wl = cs->wl;
   1257 	struct window_pane		 *wp = wme->wp;
   1258 	struct window_copy_mode_data	 *data = wme->data;
   1259 	u_int				  count = args_count(cs->wargs);
   1260 	u_int				  np = wme->prefix, ocx, ocy, ooy;
   1261 	char				 *prefix = NULL, *command = NULL;
   1262 	const char			 *arg0 = args_string(cs->wargs, 0);
   1263 	const char			 *arg1 = args_string(cs->wargs, 1);
   1264 	int				  set_paste = !args_has(cs->wargs, 'P');
   1265 	int				  set_clip = !args_has(cs->wargs, 'C');
   1266 
   1267 	if (pipe) {
   1268 		if (count == 2)
   1269 			prefix = format_single(NULL, arg1, c, s, wl, wp);
   1270 		if (s != NULL && count > 0 && *arg0 != '\0')
   1271 			command = format_single(NULL, arg0, c, s, wl, wp);
   1272 	} else {
   1273 		if (count == 1)
   1274 			prefix = format_single(NULL, arg0, c, s, wl, wp);
   1275 	}
   1276 
   1277 	ocx = data->cx;
   1278 	ocy = data->cy;
   1279 	ooy = data->oy;
   1280 
   1281 	data->selflag = SEL_CHAR;
   1282 	window_copy_cursor_start_of_line(wme);
   1283 	window_copy_start_selection(wme);
   1284 	for (; np > 1; np--)
   1285 		window_copy_cursor_down(wme, 0);
   1286 	window_copy_cursor_end_of_line(wme);
   1287 
   1288 	if (s != NULL) {
   1289 		if (pipe)
   1290 			window_copy_copy_pipe(wme, s, prefix, command,
   1291 			    set_paste, set_clip);
   1292 		else
   1293 			window_copy_copy_selection(wme, prefix,
   1294 			    set_paste, set_clip);
   1295 
   1296 		if (cancel) {
   1297 			free(prefix);
   1298 			free(command);
   1299 			return (WINDOW_COPY_CMD_CANCEL);
   1300 		}
   1301 	}
   1302 	window_copy_clear_selection(wme);
   1303 
   1304 	data->cx = ocx;
   1305 	data->cy = ocy;
   1306 	data->oy = ooy;
   1307 
   1308 	free(prefix);
   1309 	free(command);
   1310 	return (WINDOW_COPY_CMD_REDRAW);
   1311 }
   1312 
   1313 static enum window_copy_cmd_action
   1314 window_copy_cmd_copy_line(struct window_copy_cmd_state *cs)
   1315 {
   1316 	return (window_copy_do_copy_line(cs, 0, 0));
   1317 }
   1318 
   1319 static enum window_copy_cmd_action
   1320 window_copy_cmd_copy_line_and_cancel(struct window_copy_cmd_state *cs)
   1321 {
   1322 	return (window_copy_do_copy_line(cs, 0, 1));
   1323 }
   1324 
   1325 static enum window_copy_cmd_action
   1326 window_copy_cmd_copy_pipe_line(struct window_copy_cmd_state *cs)
   1327 {
   1328 	return (window_copy_do_copy_line(cs, 1, 0));
   1329 }
   1330 
   1331 static enum window_copy_cmd_action
   1332 window_copy_cmd_copy_pipe_line_and_cancel(struct window_copy_cmd_state *cs)
   1333 {
   1334 	return (window_copy_do_copy_line(cs, 1, 1));
   1335 }
   1336 
   1337 static enum window_copy_cmd_action
   1338 window_copy_cmd_copy_selection_no_clear(struct window_copy_cmd_state *cs)
   1339 {
   1340 	struct window_mode_entry	*wme = cs->wme;
   1341 	struct client			*c = cs->c;
   1342 	struct session			*s = cs->s;
   1343 	struct winlink			*wl = cs->wl;
   1344 	struct window_pane		*wp = wme->wp;
   1345 	char				*prefix = NULL;
   1346 	const char			*arg0 = args_string(cs->wargs, 0);
   1347 	int				 set_paste = !args_has(cs->wargs, 'P');
   1348 	int				 set_clip = !args_has(cs->wargs, 'C');
   1349 
   1350 	if (arg0 != NULL)
   1351 		prefix = format_single(NULL, arg0, c, s, wl, wp);
   1352 
   1353 	if (s != NULL)
   1354 		window_copy_copy_selection(wme, prefix, set_paste, set_clip);
   1355 
   1356 	free(prefix);
   1357 	return (WINDOW_COPY_CMD_NOTHING);
   1358 }
   1359 
   1360 static enum window_copy_cmd_action
   1361 window_copy_cmd_copy_selection(struct window_copy_cmd_state *cs)
   1362 {
   1363 	struct window_mode_entry	*wme = cs->wme;
   1364 
   1365 	window_copy_cmd_copy_selection_no_clear(cs);
   1366 	window_copy_clear_selection(wme);
   1367 	return (WINDOW_COPY_CMD_REDRAW);
   1368 }
   1369 
   1370 static enum window_copy_cmd_action
   1371 window_copy_cmd_copy_selection_and_cancel(struct window_copy_cmd_state *cs)
   1372 {
   1373 	struct window_mode_entry	*wme = cs->wme;
   1374 
   1375 	window_copy_cmd_copy_selection_no_clear(cs);
   1376 	window_copy_clear_selection(wme);
   1377 	return (WINDOW_COPY_CMD_CANCEL);
   1378 }
   1379 
   1380 static enum window_copy_cmd_action
   1381 window_copy_cmd_cursor_down(struct window_copy_cmd_state *cs)
   1382 {
   1383 	struct window_mode_entry	*wme = cs->wme;
   1384 	u_int				 np = wme->prefix;
   1385 
   1386 	for (; np != 0; np--)
   1387 		window_copy_cursor_down(wme, 0);
   1388 	return (WINDOW_COPY_CMD_NOTHING);
   1389 }
   1390 
   1391 static enum window_copy_cmd_action
   1392 window_copy_cmd_cursor_down_and_cancel(struct window_copy_cmd_state *cs)
   1393 {
   1394 	struct window_mode_entry	*wme = cs->wme;
   1395 	struct window_copy_mode_data	*data = wme->data;
   1396 	u_int				 np = wme->prefix, cy;
   1397 
   1398 	cy = data->cy;
   1399 	for (; np != 0; np--)
   1400 		window_copy_cursor_down(wme, 0);
   1401 	if (cy == data->cy && data->oy == 0)
   1402 		return (WINDOW_COPY_CMD_CANCEL);
   1403 	return (WINDOW_COPY_CMD_NOTHING);
   1404 }
   1405 
   1406 static enum window_copy_cmd_action
   1407 window_copy_cmd_cursor_left(struct window_copy_cmd_state *cs)
   1408 {
   1409 	struct window_mode_entry	*wme = cs->wme;
   1410 	u_int				 np = wme->prefix;
   1411 
   1412 	for (; np != 0; np--)
   1413 		window_copy_cursor_left(wme);
   1414 	return (WINDOW_COPY_CMD_NOTHING);
   1415 }
   1416 
   1417 static enum window_copy_cmd_action
   1418 window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
   1419 {
   1420 	struct window_mode_entry	*wme = cs->wme;
   1421 	struct window_copy_mode_data	*data = wme->data;
   1422 	u_int				 np = wme->prefix;
   1423 
   1424 	for (; np != 0; np--) {
   1425 		window_copy_cursor_right(wme, data->screen.sel != NULL &&
   1426 		    data->rectflag);
   1427 	}
   1428 	return (WINDOW_COPY_CMD_NOTHING);
   1429 }
   1430 
   1431 /* Scroll line containing the cursor to the given position. */
   1432 static enum window_copy_cmd_action
   1433 window_copy_cmd_scroll_to(struct window_copy_cmd_state *cs, u_int to)
   1434 {
   1435 	struct window_mode_entry	*wme = cs->wme;
   1436 	struct window_copy_mode_data	*data = wme->data;
   1437 	u_int				 oy, delta;
   1438 	int				 scroll_up; /* >0 up, <0 down */
   1439 
   1440 	scroll_up = data->cy - to;
   1441 	delta = abs(scroll_up);
   1442 	oy = screen_hsize(data->backing) - data->oy;
   1443 
   1444 	/*
   1445 	 * oy is the maximum scroll down amount, while data->oy is the maximum
   1446 	 * scroll up amount.
   1447 	 */
   1448 	if (scroll_up > 0 && data->oy >= delta) {
   1449 		window_copy_scroll_up(wme, delta);
   1450 		data->cy -= delta;
   1451 	} else if (scroll_up < 0 && oy >= delta) {
   1452 		window_copy_scroll_down(wme, delta);
   1453 		data->cy += delta;
   1454 	}
   1455 
   1456 	window_copy_update_selection(wme, 0, 0);
   1457 	return (WINDOW_COPY_CMD_REDRAW);
   1458 }
   1459 
   1460 /* Scroll line containing the cursor to the bottom. */
   1461 static enum window_copy_cmd_action
   1462 window_copy_cmd_scroll_bottom(struct window_copy_cmd_state *cs)
   1463 {
   1464 	struct window_copy_mode_data	*data = cs->wme->data;
   1465 	u_int				 bottom;
   1466 
   1467 	bottom = screen_size_y(&data->screen) - 1;
   1468 	return (window_copy_cmd_scroll_to(cs, bottom));
   1469 }
   1470 
   1471 /* Scroll line containing the cursor to the middle. */
   1472 static enum window_copy_cmd_action
   1473 window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs)
   1474 {
   1475 	struct window_copy_mode_data	*data = cs->wme->data;
   1476 	u_int				 mid_value;
   1477 
   1478 	mid_value = (screen_size_y(&data->screen) - 1) / 2;
   1479 	return (window_copy_cmd_scroll_to(cs, mid_value));
   1480 }
   1481 
   1482 /* Scroll line containing the cursor to the top. */
   1483 static enum window_copy_cmd_action
   1484 window_copy_cmd_scroll_top(struct window_copy_cmd_state *cs)
   1485 {
   1486 	return (window_copy_cmd_scroll_to(cs, 0));
   1487 }
   1488 
   1489 static enum window_copy_cmd_action
   1490 window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs)
   1491 {
   1492 	struct window_mode_entry	*wme = cs->wme;
   1493 	u_int				 np = wme->prefix;
   1494 
   1495 	for (; np != 0; np--)
   1496 		window_copy_cursor_up(wme, 0);
   1497 	return (WINDOW_COPY_CMD_NOTHING);
   1498 }
   1499 
   1500 static enum window_copy_cmd_action
   1501 window_copy_cmd_centre_vertical(struct window_copy_cmd_state *cs)
   1502 {
   1503 	struct window_mode_entry	*wme = cs->wme;
   1504 	struct window_copy_mode_data	*data = wme->data;
   1505 
   1506 	window_copy_update_cursor(wme, data->cx,  wme->wp->sy / 2);
   1507 	window_copy_update_selection(wme, 1, 0);
   1508 	return (WINDOW_COPY_CMD_REDRAW);
   1509 }
   1510 
   1511 static enum window_copy_cmd_action
   1512 window_copy_cmd_centre_horizontal(struct window_copy_cmd_state *cs)
   1513 {
   1514 	struct window_mode_entry	*wme = cs->wme;
   1515 	struct window_copy_mode_data	*data = wme->data;
   1516 
   1517 	window_copy_update_cursor(wme, wme->wp->sx / 2, data->cy);
   1518 	window_copy_update_selection(wme, 1, 0);
   1519 	return (WINDOW_COPY_CMD_REDRAW);
   1520 }
   1521 
   1522 static enum window_copy_cmd_action
   1523 window_copy_cmd_end_of_line(struct window_copy_cmd_state *cs)
   1524 {
   1525 	struct window_mode_entry	*wme = cs->wme;
   1526 
   1527 	window_copy_cursor_end_of_line(wme);
   1528 	return (WINDOW_COPY_CMD_NOTHING);
   1529 }
   1530 
   1531 static enum window_copy_cmd_action
   1532 window_copy_cmd_halfpage_down(struct window_copy_cmd_state *cs)
   1533 {
   1534 	struct window_mode_entry	*wme = cs->wme;
   1535 	struct window_copy_mode_data	*data = wme->data;
   1536 	u_int				 np = wme->prefix;
   1537 
   1538 	for (; np != 0; np--) {
   1539 		if (window_copy_pagedown1(wme, 1, data->scroll_exit))
   1540 			return (WINDOW_COPY_CMD_CANCEL);
   1541 	}
   1542 	return (WINDOW_COPY_CMD_NOTHING);
   1543 }
   1544 
   1545 static enum window_copy_cmd_action
   1546 window_copy_cmd_halfpage_down_and_cancel(struct window_copy_cmd_state *cs)
   1547 {
   1548 
   1549 	struct window_mode_entry	*wme = cs->wme;
   1550 	u_int				 np = wme->prefix;
   1551 
   1552 	for (; np != 0; np--) {
   1553 		if (window_copy_pagedown1(wme, 1, 1))
   1554 			return (WINDOW_COPY_CMD_CANCEL);
   1555 	}
   1556 	return (WINDOW_COPY_CMD_NOTHING);
   1557 }
   1558 
   1559 static enum window_copy_cmd_action
   1560 window_copy_cmd_halfpage_up(struct window_copy_cmd_state *cs)
   1561 {
   1562 	struct window_mode_entry	*wme = cs->wme;
   1563 	u_int				 np = wme->prefix;
   1564 
   1565 	for (; np != 0; np--)
   1566 		window_copy_pageup1(wme, 1);
   1567 	return (WINDOW_COPY_CMD_NOTHING);
   1568 }
   1569 
   1570 static enum window_copy_cmd_action
   1571 window_copy_cmd_toggle_position(struct window_copy_cmd_state *cs)
   1572 {
   1573 	struct window_mode_entry	*wme = cs->wme;
   1574 	struct window_copy_mode_data	*data = wme->data;
   1575 
   1576 	data->hide_position = !data->hide_position;
   1577 	return (WINDOW_COPY_CMD_REDRAW);
   1578 }
   1579 
   1580 static enum window_copy_cmd_action
   1581 window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs)
   1582 {
   1583 	struct window_mode_entry	*wme = cs->wme;
   1584 	struct window_copy_mode_data	*data = wme->data;
   1585 	struct screen			*s = data->backing;
   1586 	u_int				 oy;
   1587 
   1588 	oy = screen_hsize(s) + data->cy - data->oy;
   1589 	if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
   1590 		window_copy_other_end(wme);
   1591 
   1592 	data->cy = screen_size_y(&data->screen) - 1;
   1593 	data->cx = window_copy_find_length(wme, screen_hsize(s) + data->cy);
   1594 	data->oy = 0;
   1595 
   1596 	if (data->searchmark != NULL && !data->timeout)
   1597 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
   1598 	window_copy_update_selection(wme, 1, 0);
   1599 	return (WINDOW_COPY_CMD_REDRAW);
   1600 }
   1601 
   1602 static enum window_copy_cmd_action
   1603 window_copy_cmd_history_top(struct window_copy_cmd_state *cs)
   1604 {
   1605 	struct window_mode_entry	*wme = cs->wme;
   1606 	struct window_copy_mode_data	*data = wme->data;
   1607 	u_int				 oy;
   1608 
   1609 	oy = screen_hsize(data->backing) + data->cy - data->oy;
   1610 	if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
   1611 		window_copy_other_end(wme);
   1612 
   1613 	data->cy = 0;
   1614 	data->cx = 0;
   1615 	data->oy = screen_hsize(data->backing);
   1616 
   1617 	if (data->searchmark != NULL && !data->timeout)
   1618 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
   1619 	window_copy_update_selection(wme, 1, 0);
   1620 	return (WINDOW_COPY_CMD_REDRAW);
   1621 }
   1622 
   1623 static enum window_copy_cmd_action
   1624 window_copy_cmd_jump_again(struct window_copy_cmd_state *cs)
   1625 {
   1626 	struct window_mode_entry	*wme = cs->wme;
   1627 	struct window_copy_mode_data	*data = wme->data;
   1628 	u_int				 np = wme->prefix;
   1629 
   1630 	switch (data->jumptype) {
   1631 	case WINDOW_COPY_JUMPFORWARD:
   1632 		for (; np != 0; np--)
   1633 			window_copy_cursor_jump(wme);
   1634 		break;
   1635 	case WINDOW_COPY_JUMPBACKWARD:
   1636 		for (; np != 0; np--)
   1637 			window_copy_cursor_jump_back(wme);
   1638 		break;
   1639 	case WINDOW_COPY_JUMPTOFORWARD:
   1640 		for (; np != 0; np--)
   1641 			window_copy_cursor_jump_to(wme);
   1642 		break;
   1643 	case WINDOW_COPY_JUMPTOBACKWARD:
   1644 		for (; np != 0; np--)
   1645 			window_copy_cursor_jump_to_back(wme);
   1646 		break;
   1647 	}
   1648 	return (WINDOW_COPY_CMD_NOTHING);
   1649 }
   1650 
   1651 static enum window_copy_cmd_action
   1652 window_copy_cmd_jump_reverse(struct window_copy_cmd_state *cs)
   1653 {
   1654 	struct window_mode_entry	*wme = cs->wme;
   1655 	struct window_copy_mode_data	*data = wme->data;
   1656 	u_int				 np = wme->prefix;
   1657 
   1658 	switch (data->jumptype) {
   1659 	case WINDOW_COPY_JUMPFORWARD:
   1660 		for (; np != 0; np--)
   1661 			window_copy_cursor_jump_back(wme);
   1662 		break;
   1663 	case WINDOW_COPY_JUMPBACKWARD:
   1664 		for (; np != 0; np--)
   1665 			window_copy_cursor_jump(wme);
   1666 		break;
   1667 	case WINDOW_COPY_JUMPTOFORWARD:
   1668 		for (; np != 0; np--)
   1669 			window_copy_cursor_jump_to_back(wme);
   1670 		break;
   1671 	case WINDOW_COPY_JUMPTOBACKWARD:
   1672 		for (; np != 0; np--)
   1673 			window_copy_cursor_jump_to(wme);
   1674 		break;
   1675 	}
   1676 	return (WINDOW_COPY_CMD_NOTHING);
   1677 }
   1678 
   1679 static enum window_copy_cmd_action
   1680 window_copy_cmd_middle_line(struct window_copy_cmd_state *cs)
   1681 {
   1682 	struct window_mode_entry	*wme = cs->wme;
   1683 	struct window_copy_mode_data	*data = wme->data;
   1684 
   1685 	data->cx = 0;
   1686 	data->cy = (screen_size_y(&data->screen) - 1) / 2;
   1687 
   1688 	window_copy_update_selection(wme, 1, 0);
   1689 	return (WINDOW_COPY_CMD_REDRAW);
   1690 }
   1691 
   1692 static enum window_copy_cmd_action
   1693 window_copy_cmd_previous_matching_bracket(struct window_copy_cmd_state *cs)
   1694 {
   1695 	struct window_mode_entry	*wme = cs->wme;
   1696 	u_int				 np = wme->prefix;
   1697 	struct window_copy_mode_data	*data = wme->data;
   1698 	struct screen			*s = data->backing;
   1699 	char				 open[] = "{[(", close[] = "}])";
   1700 	char				 tried, found, start, *cp;
   1701 	u_int				 px, py, xx, n;
   1702 	struct grid_cell		 gc;
   1703 	int				 failed;
   1704 
   1705 	for (; np != 0; np--) {
   1706 		/* Get cursor position and line length. */
   1707 		px = data->cx;
   1708 		py = screen_hsize(s) + data->cy - data->oy;
   1709 		xx = window_copy_find_length(wme, py);
   1710 		if (xx == 0)
   1711 			break;
   1712 
   1713 		/*
   1714 		 * Get the current character. If not on a bracket, try the
   1715 		 * previous. If still not, then behave like previous-word.
   1716 		 */
   1717 		tried = 0;
   1718 	retry:
   1719 		grid_get_cell(s->grid, px, py, &gc);
   1720 		if (gc.data.size != 1 || (gc.flags & GRID_FLAG_PADDING))
   1721 			cp = NULL;
   1722 		else {
   1723 			found = *gc.data.data;
   1724 			cp = strchr(close, found);
   1725 		}
   1726 		if (cp == NULL) {
   1727 			if (data->modekeys == MODEKEY_EMACS) {
   1728 				if (!tried && px > 0) {
   1729 					px--;
   1730 					tried = 1;
   1731 					goto retry;
   1732 				}
   1733 				window_copy_cursor_previous_word(wme, close, 1);
   1734 			}
   1735 			continue;
   1736 		}
   1737 		start = open[cp - close];
   1738 
   1739 		/* Walk backward until the matching bracket is reached. */
   1740 		n = 1;
   1741 		failed = 0;
   1742 		do {
   1743 			if (px == 0) {
   1744 				if (py == 0) {
   1745 					failed = 1;
   1746 					break;
   1747 				}
   1748 				do {
   1749 					py--;
   1750 					xx = window_copy_find_length(wme, py);
   1751 				} while (xx == 0 && py > 0);
   1752 				if (xx == 0 && py == 0) {
   1753 					failed = 1;
   1754 					break;
   1755 				}
   1756 				px = xx - 1;
   1757 			} else
   1758 				px--;
   1759 
   1760 			grid_get_cell(s->grid, px, py, &gc);
   1761 			if (gc.data.size == 1 &&
   1762 			    (~gc.flags & GRID_FLAG_PADDING)) {
   1763 				if (*gc.data.data == found)
   1764 					n++;
   1765 				else if (*gc.data.data == start)
   1766 					n--;
   1767 			}
   1768 		} while (n != 0);
   1769 
   1770 		/* Move the cursor to the found location if any. */
   1771 		if (!failed)
   1772 			window_copy_scroll_to(wme, px, py, 0);
   1773 	}
   1774 
   1775 	return (WINDOW_COPY_CMD_NOTHING);
   1776 }
   1777 
   1778 static enum window_copy_cmd_action
   1779 window_copy_cmd_next_matching_bracket(struct window_copy_cmd_state *cs)
   1780 {
   1781 	struct window_mode_entry	*wme = cs->wme;
   1782 	u_int				 np = wme->prefix;
   1783 	struct window_copy_mode_data	*data = wme->data;
   1784 	struct screen			*s = data->backing;
   1785 	char				 open[] = "{[(", close[] = "}])";
   1786 	char				 tried, found, end, *cp;
   1787 	u_int				 px, py, xx, yy, sx, sy, n;
   1788 	struct grid_cell		 gc;
   1789 	int				 failed;
   1790 	struct grid_line		*gl;
   1791 
   1792 	for (; np != 0; np--) {
   1793 		/* Get cursor position and line length. */
   1794 		px = data->cx;
   1795 		py = screen_hsize(s) + data->cy - data->oy;
   1796 		xx = window_copy_find_length(wme, py);
   1797 		yy = screen_hsize(s) + screen_size_y(s) - 1;
   1798 		if (xx == 0)
   1799 			break;
   1800 
   1801 		/*
   1802 		 * Get the current character. If not on a bracket, try the
   1803 		 * next. If still not, then behave like next-word.
   1804 		 */
   1805 		tried = 0;
   1806 	retry:
   1807 		grid_get_cell(s->grid, px, py, &gc);
   1808 		if (gc.data.size != 1 || (gc.flags & GRID_FLAG_PADDING))
   1809 			cp = NULL;
   1810 		else {
   1811 			found = *gc.data.data;
   1812 
   1813 			/*
   1814 			 * In vi mode, attempt to move to previous bracket if a
   1815 			 * closing bracket is found first. If this fails,
   1816 			 * return to the original cursor position.
   1817 			 */
   1818 			cp = strchr(close, found);
   1819 			if (cp != NULL && data->modekeys == MODEKEY_VI) {
   1820 				sx = data->cx;
   1821 				sy = screen_hsize(s) + data->cy - data->oy;
   1822 
   1823 				window_copy_scroll_to(wme, px, py, 0);
   1824 				window_copy_cmd_previous_matching_bracket(cs);
   1825 
   1826 				px = data->cx;
   1827 				py = screen_hsize(s) + data->cy - data->oy;
   1828 				grid_get_cell(s->grid, px, py, &gc);
   1829 				if (gc.data.size == 1 &&
   1830 				    (~gc.flags & GRID_FLAG_PADDING) &&
   1831 				    strchr(close, *gc.data.data) != NULL)
   1832 					window_copy_scroll_to(wme, sx, sy, 0);
   1833 				break;
   1834 			}
   1835 
   1836 			cp = strchr(open, found);
   1837 		}
   1838 		if (cp == NULL) {
   1839 			if (data->modekeys == MODEKEY_EMACS) {
   1840 				if (!tried && px <= xx) {
   1841 					px++;
   1842 					tried = 1;
   1843 					goto retry;
   1844 				}
   1845 				window_copy_cursor_next_word_end(wme, open, 0);
   1846 				continue;
   1847 			}
   1848 			/* For vi, continue searching for bracket until EOL. */
   1849 			if (px > xx) {
   1850 				if (py == yy)
   1851 					continue;
   1852 				gl = grid_get_line(s->grid, py);
   1853 				if (~gl->flags & GRID_LINE_WRAPPED)
   1854 					continue;
   1855 				if (gl->cellsize > s->grid->sx)
   1856 					continue;
   1857 				px = 0;
   1858 				py++;
   1859 				xx = window_copy_find_length(wme, py);
   1860 			} else
   1861 				px++;
   1862 			goto retry;
   1863 		}
   1864 		end = close[cp - open];
   1865 
   1866 		/* Walk forward until the matching bracket is reached. */
   1867 		n = 1;
   1868 		failed = 0;
   1869 		do {
   1870 			if (px > xx) {
   1871 				if (py == yy) {
   1872 					failed = 1;
   1873 					break;
   1874 				}
   1875 				px = 0;
   1876 				py++;
   1877 				xx = window_copy_find_length(wme, py);
   1878 			} else
   1879 				px++;
   1880 
   1881 			grid_get_cell(s->grid, px, py, &gc);
   1882 			if (gc.data.size == 1 &&
   1883 			    (~gc.flags & GRID_FLAG_PADDING)) {
   1884 				if (*gc.data.data == found)
   1885 					n++;
   1886 				else if (*gc.data.data == end)
   1887 					n--;
   1888 			}
   1889 		} while (n != 0);
   1890 
   1891 		/* Move the cursor to the found location if any. */
   1892 		if (!failed)
   1893 			window_copy_scroll_to(wme, px, py, 0);
   1894 	}
   1895 
   1896 	return (WINDOW_COPY_CMD_NOTHING);
   1897 }
   1898 
   1899 static enum window_copy_cmd_action
   1900 window_copy_cmd_next_paragraph(struct window_copy_cmd_state *cs)
   1901 {
   1902 	struct window_mode_entry	*wme = cs->wme;
   1903 	u_int				 np = wme->prefix;
   1904 
   1905 	for (; np != 0; np--)
   1906 		window_copy_next_paragraph(wme);
   1907 	return (WINDOW_COPY_CMD_NOTHING);
   1908 }
   1909 
   1910 static enum window_copy_cmd_action
   1911 window_copy_cmd_next_space(struct window_copy_cmd_state *cs)
   1912 {
   1913 	struct window_mode_entry	*wme = cs->wme;
   1914 	u_int				 np = wme->prefix;
   1915 
   1916 	for (; np != 0; np--)
   1917 		window_copy_cursor_next_word(wme, "");
   1918 	return (WINDOW_COPY_CMD_NOTHING);
   1919 }
   1920 
   1921 static enum window_copy_cmd_action
   1922 window_copy_cmd_next_space_end(struct window_copy_cmd_state *cs)
   1923 {
   1924 	struct window_mode_entry	*wme = cs->wme;
   1925 	u_int				 np = wme->prefix;
   1926 
   1927 	for (; np != 0; np--)
   1928 		window_copy_cursor_next_word_end(wme, "", 0);
   1929 	return (WINDOW_COPY_CMD_NOTHING);
   1930 }
   1931 
   1932 static enum window_copy_cmd_action
   1933 window_copy_cmd_next_word(struct window_copy_cmd_state *cs)
   1934 {
   1935 	struct window_mode_entry	*wme = cs->wme;
   1936 	u_int				 np = wme->prefix;
   1937 	const char			*separators;
   1938 
   1939 	separators = options_get_string(cs->s->options, "word-separators");
   1940 
   1941 	for (; np != 0; np--)
   1942 		window_copy_cursor_next_word(wme, separators);
   1943 	return (WINDOW_COPY_CMD_NOTHING);
   1944 }
   1945 
   1946 static enum window_copy_cmd_action
   1947 window_copy_cmd_next_word_end(struct window_copy_cmd_state *cs)
   1948 {
   1949 	struct window_mode_entry	*wme = cs->wme;
   1950 	u_int				 np = wme->prefix;
   1951 	const char			*separators;
   1952 
   1953 	separators = options_get_string(cs->s->options, "word-separators");
   1954 
   1955 	for (; np != 0; np--)
   1956 		window_copy_cursor_next_word_end(wme, separators, 0);
   1957 	return (WINDOW_COPY_CMD_NOTHING);
   1958 }
   1959 
   1960 static enum window_copy_cmd_action
   1961 window_copy_cmd_other_end(struct window_copy_cmd_state *cs)
   1962 {
   1963 	struct window_mode_entry	*wme = cs->wme;
   1964 	u_int				 np = wme->prefix;
   1965 	struct window_copy_mode_data	*data = wme->data;
   1966 
   1967 	data->selflag = SEL_CHAR;
   1968 	if ((np % 2) != 0)
   1969 		window_copy_other_end(wme);
   1970 	return (WINDOW_COPY_CMD_NOTHING);
   1971 }
   1972 
   1973 static enum window_copy_cmd_action
   1974 window_copy_cmd_selection_mode(struct window_copy_cmd_state *cs)
   1975 {
   1976 	struct window_mode_entry	*wme = cs->wme;
   1977 	struct options			*so = cs->s->options;
   1978 	struct window_copy_mode_data	*data = wme->data;
   1979 	const char			*s = args_string(cs->wargs, 0);
   1980 
   1981 	if (s == NULL || strcasecmp(s, "char") == 0 || strcasecmp(s, "c") == 0)
   1982 		data->selflag = SEL_CHAR;
   1983 	else if (strcasecmp(s, "word") == 0 || strcasecmp(s, "w") == 0) {
   1984 		data->separators = options_get_string(so, "word-separators");
   1985 		data->selflag = SEL_WORD;
   1986 	} else if (strcasecmp(s, "line") == 0 || strcasecmp(s, "l") == 0)
   1987 		data->selflag = SEL_LINE;
   1988 	return (WINDOW_COPY_CMD_NOTHING);
   1989 }
   1990 
   1991 static enum window_copy_cmd_action
   1992 window_copy_cmd_page_down(struct window_copy_cmd_state *cs)
   1993 {
   1994 	struct window_mode_entry	*wme = cs->wme;
   1995 	struct window_copy_mode_data	*data = wme->data;
   1996 	u_int				 np = wme->prefix;
   1997 
   1998 	for (; np != 0; np--) {
   1999 		if (window_copy_pagedown1(wme, 0, data->scroll_exit))
   2000 			return (WINDOW_COPY_CMD_CANCEL);
   2001 	}
   2002 	return (WINDOW_COPY_CMD_NOTHING);
   2003 }
   2004 
   2005 static enum window_copy_cmd_action
   2006 window_copy_cmd_page_down_and_cancel(struct window_copy_cmd_state *cs)
   2007 {
   2008 	struct window_mode_entry	*wme = cs->wme;
   2009 	u_int				 np = wme->prefix;
   2010 
   2011 	for (; np != 0; np--) {
   2012 		if (window_copy_pagedown1(wme, 0, 1))
   2013 			return (WINDOW_COPY_CMD_CANCEL);
   2014 	}
   2015 	return (WINDOW_COPY_CMD_NOTHING);
   2016 }
   2017 
   2018 static enum window_copy_cmd_action
   2019 window_copy_cmd_page_up(struct window_copy_cmd_state *cs)
   2020 {
   2021 	struct window_mode_entry	*wme = cs->wme;
   2022 	u_int				 np = wme->prefix;
   2023 
   2024 	for (; np != 0; np--)
   2025 		window_copy_pageup1(wme, 0);
   2026 	return (WINDOW_COPY_CMD_NOTHING);
   2027 }
   2028 
   2029 static enum window_copy_cmd_action
   2030 window_copy_cmd_previous_paragraph(struct window_copy_cmd_state *cs)
   2031 {
   2032 	struct window_mode_entry	*wme = cs->wme;
   2033 	u_int				 np = wme->prefix;
   2034 
   2035 	for (; np != 0; np--)
   2036 		window_copy_previous_paragraph(wme);
   2037 	return (WINDOW_COPY_CMD_NOTHING);
   2038 }
   2039 
   2040 static enum window_copy_cmd_action
   2041 window_copy_cmd_previous_space(struct window_copy_cmd_state *cs)
   2042 {
   2043 	struct window_mode_entry	*wme = cs->wme;
   2044 	u_int				 np = wme->prefix;
   2045 
   2046 	for (; np != 0; np--)
   2047 		window_copy_cursor_previous_word(wme, "", 1);
   2048 	return (WINDOW_COPY_CMD_NOTHING);
   2049 }
   2050 
   2051 static enum window_copy_cmd_action
   2052 window_copy_cmd_previous_word(struct window_copy_cmd_state *cs)
   2053 {
   2054 	struct window_mode_entry	*wme = cs->wme;
   2055 	u_int				 np = wme->prefix;
   2056 	const char			*separators;
   2057 
   2058 	separators = options_get_string(cs->s->options, "word-separators");
   2059 
   2060 	for (; np != 0; np--)
   2061 		window_copy_cursor_previous_word(wme, separators, 1);
   2062 	return (WINDOW_COPY_CMD_NOTHING);
   2063 }
   2064 
   2065 static enum window_copy_cmd_action
   2066 window_copy_cmd_rectangle_on(struct window_copy_cmd_state *cs)
   2067 {
   2068 	struct window_mode_entry	*wme = cs->wme;
   2069 	struct window_copy_mode_data	*data = wme->data;
   2070 
   2071 	data->lineflag = LINE_SEL_NONE;
   2072 	window_copy_rectangle_set(wme, 1);
   2073 
   2074 	return (WINDOW_COPY_CMD_NOTHING);
   2075 }
   2076 
   2077 static enum window_copy_cmd_action
   2078 window_copy_cmd_rectangle_off(struct window_copy_cmd_state *cs)
   2079 {
   2080 	struct window_mode_entry	*wme = cs->wme;
   2081 	struct window_copy_mode_data	*data = wme->data;
   2082 
   2083 	data->lineflag = LINE_SEL_NONE;
   2084 	window_copy_rectangle_set(wme, 0);
   2085 
   2086 	return (WINDOW_COPY_CMD_NOTHING);
   2087 }
   2088 
   2089 static enum window_copy_cmd_action
   2090 window_copy_cmd_rectangle_toggle(struct window_copy_cmd_state *cs)
   2091 {
   2092 	struct window_mode_entry	*wme = cs->wme;
   2093 	struct window_copy_mode_data	*data = wme->data;
   2094 
   2095 	data->lineflag = LINE_SEL_NONE;
   2096 	window_copy_rectangle_set(wme, !data->rectflag);
   2097 
   2098 	return (WINDOW_COPY_CMD_NOTHING);
   2099 }
   2100 
   2101 static enum window_copy_cmd_action
   2102 window_copy_cmd_scroll_down(struct window_copy_cmd_state *cs)
   2103 {
   2104 	struct window_mode_entry	*wme = cs->wme;
   2105 	struct window_copy_mode_data	*data = wme->data;
   2106 	u_int				 np = wme->prefix;
   2107 
   2108 	for (; np != 0; np--)
   2109 		window_copy_cursor_down(wme, 1);
   2110 	if (data->scroll_exit && data->oy == 0)
   2111 		return (WINDOW_COPY_CMD_CANCEL);
   2112 	return (WINDOW_COPY_CMD_NOTHING);
   2113 }
   2114 
   2115 static enum window_copy_cmd_action
   2116 window_copy_cmd_scroll_down_and_cancel(struct window_copy_cmd_state *cs)
   2117 {
   2118 	struct window_mode_entry	*wme = cs->wme;
   2119 	struct window_copy_mode_data	*data = wme->data;
   2120 	u_int				 np = wme->prefix;
   2121 
   2122 	for (; np != 0; np--)
   2123 		window_copy_cursor_down(wme, 1);
   2124 	if (data->oy == 0)
   2125 		return (WINDOW_COPY_CMD_CANCEL);
   2126 	return (WINDOW_COPY_CMD_NOTHING);
   2127 }
   2128 
   2129 static enum window_copy_cmd_action
   2130 window_copy_cmd_scroll_up(struct window_copy_cmd_state *cs)
   2131 {
   2132 	struct window_mode_entry	*wme = cs->wme;
   2133 	u_int				 np = wme->prefix;
   2134 
   2135 	for (; np != 0; np--)
   2136 		window_copy_cursor_up(wme, 1);
   2137 	return (WINDOW_COPY_CMD_NOTHING);
   2138 }
   2139 
   2140 static enum window_copy_cmd_action
   2141 window_copy_cmd_search_again(struct window_copy_cmd_state *cs)
   2142 {
   2143 	struct window_mode_entry	*wme = cs->wme;
   2144 	struct window_copy_mode_data	*data = wme->data;
   2145 	u_int				 np = wme->prefix;
   2146 
   2147 	if (data->searchtype == WINDOW_COPY_SEARCHUP) {
   2148 		for (; np != 0; np--)
   2149 			window_copy_search_up(wme, data->searchregex);
   2150 	} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
   2151 		for (; np != 0; np--)
   2152 			window_copy_search_down(wme, data->searchregex);
   2153 	}
   2154 	return (WINDOW_COPY_CMD_NOTHING);
   2155 }
   2156 
   2157 static enum window_copy_cmd_action
   2158 window_copy_cmd_search_reverse(struct window_copy_cmd_state *cs)
   2159 {
   2160 	struct window_mode_entry	*wme = cs->wme;
   2161 	struct window_copy_mode_data	*data = wme->data;
   2162 	u_int				 np = wme->prefix;
   2163 
   2164 	if (data->searchtype == WINDOW_COPY_SEARCHUP) {
   2165 		for (; np != 0; np--)
   2166 			window_copy_search_down(wme, data->searchregex);
   2167 	} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) {
   2168 		for (; np != 0; np--)
   2169 			window_copy_search_up(wme, data->searchregex);
   2170 	}
   2171 	return (WINDOW_COPY_CMD_NOTHING);
   2172 }
   2173 
   2174 static enum window_copy_cmd_action
   2175 window_copy_cmd_select_line(struct window_copy_cmd_state *cs)
   2176 {
   2177 	struct window_mode_entry	*wme = cs->wme;
   2178 	struct window_copy_mode_data	*data = wme->data;
   2179 	u_int				 np = wme->prefix;
   2180 
   2181 	data->lineflag = LINE_SEL_LEFT_RIGHT;
   2182 	data->rectflag = 0;
   2183 	data->selflag = SEL_LINE;
   2184 	data->dx = data->cx;
   2185 	data->dy = screen_hsize(data->backing) + data->cy - data->oy;
   2186 
   2187 	window_copy_cursor_start_of_line(wme);
   2188 	data->selrx = data->cx;
   2189 	data->selry = screen_hsize(data->backing) + data->cy - data->oy;
   2190 	data->endselry = data->selry;
   2191 	window_copy_start_selection(wme);
   2192 	window_copy_cursor_end_of_line(wme);
   2193 	data->endselry = screen_hsize(data->backing) + data->cy - data->oy;
   2194 	data->endselrx = window_copy_find_length(wme, data->endselry);
   2195 	for (; np > 1; np--) {
   2196 		window_copy_cursor_down(wme, 0);
   2197 		window_copy_cursor_end_of_line(wme);
   2198 	}
   2199 
   2200 	return (WINDOW_COPY_CMD_REDRAW);
   2201 }
   2202 
   2203 static enum window_copy_cmd_action
   2204 window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
   2205 {
   2206 	struct window_mode_entry	*wme = cs->wme;
   2207 	struct options			*so = cs->s->options;
   2208 	struct window_copy_mode_data	*data = wme->data;
   2209 	u_int				 px, py, nextx, nexty;
   2210 
   2211 	data->lineflag = LINE_SEL_LEFT_RIGHT;
   2212 	data->rectflag = 0;
   2213 	data->selflag = SEL_WORD;
   2214 	data->dx = data->cx;
   2215 	data->dy = screen_hsize(data->backing) + data->cy - data->oy;
   2216 
   2217 	data->separators = options_get_string(so, "word-separators");
   2218 	window_copy_cursor_previous_word(wme, data->separators, 0);
   2219 	px = data->cx;
   2220 	py = screen_hsize(data->backing) + data->cy - data->oy;
   2221 	data->selrx = px;
   2222 	data->selry = py;
   2223 	window_copy_start_selection(wme);
   2224 
   2225 	/* Handle single character words. */
   2226 	nextx = px + 1;
   2227 	nexty = py;
   2228 	if (grid_get_line(data->backing->grid, nexty)->flags &
   2229 	    GRID_LINE_WRAPPED && nextx > screen_size_x(data->backing) - 1) {
   2230 		nextx = 0;
   2231 		nexty++;
   2232 	}
   2233 	if (px >= window_copy_find_length(wme, py) ||
   2234 	    !window_copy_in_set(wme, nextx, nexty, WHITESPACE))
   2235 		window_copy_cursor_next_word_end(wme, data->separators, 1);
   2236 	else {
   2237 		window_copy_update_cursor(wme, px, data->cy);
   2238 		if (window_copy_update_selection(wme, 1, 1))
   2239 			window_copy_redraw_lines(wme, data->cy, 1);
   2240 	}
   2241 	data->endselrx = data->cx;
   2242 	data->endselry = screen_hsize(data->backing) + data->cy - data->oy;
   2243 	if (data->dy > data->endselry) {
   2244 		data->dy = data->endselry;
   2245 		data->dx = data->endselrx;
   2246 	} else if (data->dx > data->endselrx)
   2247 		data->dx = data->endselrx;
   2248 
   2249 	return (WINDOW_COPY_CMD_REDRAW);
   2250 }
   2251 
   2252 static enum window_copy_cmd_action
   2253 window_copy_cmd_set_mark(struct window_copy_cmd_state *cs)
   2254 {
   2255 	struct window_copy_mode_data	*data = cs->wme->data;
   2256 
   2257 	data->mx = data->cx;
   2258 	data->my = screen_hsize(data->backing) + data->cy - data->oy;
   2259 	data->showmark = 1;
   2260 	return (WINDOW_COPY_CMD_REDRAW);
   2261 }
   2262 
   2263 static enum window_copy_cmd_action
   2264 window_copy_cmd_start_of_line(struct window_copy_cmd_state *cs)
   2265 {
   2266 	struct window_mode_entry	*wme = cs->wme;
   2267 
   2268 	window_copy_cursor_start_of_line(wme);
   2269 	return (WINDOW_COPY_CMD_NOTHING);
   2270 }
   2271 
   2272 static enum window_copy_cmd_action
   2273 window_copy_cmd_top_line(struct window_copy_cmd_state *cs)
   2274 {
   2275 	struct window_mode_entry	*wme = cs->wme;
   2276 	struct window_copy_mode_data	*data = wme->data;
   2277 
   2278 	data->cx = 0;
   2279 	data->cy = 0;
   2280 
   2281 	window_copy_update_selection(wme, 1, 0);
   2282 	return (WINDOW_COPY_CMD_REDRAW);
   2283 }
   2284 
   2285 static enum window_copy_cmd_action
   2286 window_copy_cmd_copy_pipe_no_clear(struct window_copy_cmd_state *cs)
   2287 {
   2288 	struct window_mode_entry	*wme = cs->wme;
   2289 	struct client			*c = cs->c;
   2290 	struct session			*s = cs->s;
   2291 	struct winlink			*wl = cs->wl;
   2292 	struct window_pane		*wp = wme->wp;
   2293 	char				*command = NULL, *prefix = NULL;
   2294 	const char			*arg0 = args_string(cs->wargs, 0);
   2295 	const char			*arg1 = args_string(cs->wargs, 1);
   2296 	int				 set_paste = !args_has(cs->wargs, 'P');
   2297 	int				 set_clip = !args_has(cs->wargs, 'C');
   2298 
   2299 	if (arg1 != NULL)
   2300 		prefix = format_single(NULL, arg1, c, s, wl, wp);
   2301 
   2302 	if (s != NULL && arg0 != NULL && *arg0 != '\0')
   2303 		command = format_single(NULL, arg0, c, s, wl, wp);
   2304 	window_copy_copy_pipe(wme, s, prefix, command,
   2305 	    set_paste, set_clip);
   2306 	free(command);
   2307 
   2308 	free(prefix);
   2309 	return (WINDOW_COPY_CMD_NOTHING);
   2310 }
   2311 
   2312 static enum window_copy_cmd_action
   2313 window_copy_cmd_copy_pipe(struct window_copy_cmd_state *cs)
   2314 {
   2315 	struct window_mode_entry	*wme = cs->wme;
   2316 
   2317 	window_copy_cmd_copy_pipe_no_clear(cs);
   2318 	window_copy_clear_selection(wme);
   2319 	return (WINDOW_COPY_CMD_REDRAW);
   2320 }
   2321 
   2322 static enum window_copy_cmd_action
   2323 window_copy_cmd_copy_pipe_and_cancel(struct window_copy_cmd_state *cs)
   2324 {
   2325 	struct window_mode_entry	*wme = cs->wme;
   2326 
   2327 	window_copy_cmd_copy_pipe_no_clear(cs);
   2328 	window_copy_clear_selection(wme);
   2329 	return (WINDOW_COPY_CMD_CANCEL);
   2330 }
   2331 
   2332 static enum window_copy_cmd_action
   2333 window_copy_cmd_pipe_no_clear(struct window_copy_cmd_state *cs)
   2334 {
   2335 	struct window_mode_entry	*wme = cs->wme;
   2336 	struct client			*c = cs->c;
   2337 	struct session			*s = cs->s;
   2338 	struct winlink			*wl = cs->wl;
   2339 	struct window_pane		*wp = wme->wp;
   2340 	char				*command = NULL;
   2341 	const char			*arg0 = args_string(cs->wargs, 0);
   2342 
   2343 	if (s != NULL && arg0 != NULL && *arg0 != '\0')
   2344 		command = format_single(NULL, arg0, c, s, wl, wp);
   2345 	window_copy_pipe(wme, s, command);
   2346 	free(command);
   2347 
   2348 	return (WINDOW_COPY_CMD_NOTHING);
   2349 }
   2350 
   2351 static enum window_copy_cmd_action
   2352 window_copy_cmd_pipe(struct window_copy_cmd_state *cs)
   2353 {
   2354 	struct window_mode_entry	*wme = cs->wme;
   2355 
   2356 	window_copy_cmd_pipe_no_clear(cs);
   2357 	window_copy_clear_selection(wme);
   2358 	return (WINDOW_COPY_CMD_REDRAW);
   2359 }
   2360 
   2361 static enum window_copy_cmd_action
   2362 window_copy_cmd_pipe_and_cancel(struct window_copy_cmd_state *cs)
   2363 {
   2364 	struct window_mode_entry	*wme = cs->wme;
   2365 
   2366 	window_copy_cmd_pipe_no_clear(cs);
   2367 	window_copy_clear_selection(wme);
   2368 	return (WINDOW_COPY_CMD_CANCEL);
   2369 }
   2370 
   2371 static enum window_copy_cmd_action
   2372 window_copy_cmd_goto_line(struct window_copy_cmd_state *cs)
   2373 {
   2374 	struct window_mode_entry	*wme = cs->wme;
   2375 	const char			*arg0 = args_string(cs->wargs, 0);
   2376 
   2377 	if (*arg0 != '\0')
   2378 		window_copy_goto_line(wme, arg0);
   2379 	return (WINDOW_COPY_CMD_NOTHING);
   2380 }
   2381 
   2382 static enum window_copy_cmd_action
   2383 window_copy_cmd_jump_backward(struct window_copy_cmd_state *cs)
   2384 {
   2385 	struct window_mode_entry	*wme = cs->wme;
   2386 	struct window_copy_mode_data	*data = wme->data;
   2387 	u_int				 np = wme->prefix;
   2388 	const char			*arg0 = args_string(cs->wargs, 0);
   2389 
   2390 	if (*arg0 != '\0') {
   2391 		data->jumptype = WINDOW_COPY_JUMPBACKWARD;
   2392 		free(data->jumpchar);
   2393 		data->jumpchar = utf8_fromcstr(arg0);
   2394 		for (; np != 0; np--)
   2395 			window_copy_cursor_jump_back(wme);
   2396 	}
   2397 	return (WINDOW_COPY_CMD_NOTHING);
   2398 }
   2399 
   2400 static enum window_copy_cmd_action
   2401 window_copy_cmd_jump_forward(struct window_copy_cmd_state *cs)
   2402 {
   2403 	struct window_mode_entry	*wme = cs->wme;
   2404 	struct window_copy_mode_data	*data = wme->data;
   2405 	u_int				 np = wme->prefix;
   2406 	const char			*arg0 = args_string(cs->wargs, 0);
   2407 
   2408 	if (*arg0 != '\0') {
   2409 		data->jumptype = WINDOW_COPY_JUMPFORWARD;
   2410 		free(data->jumpchar);
   2411 		data->jumpchar = utf8_fromcstr(arg0);
   2412 		for (; np != 0; np--)
   2413 			window_copy_cursor_jump(wme);
   2414 	}
   2415 	return (WINDOW_COPY_CMD_NOTHING);
   2416 }
   2417 
   2418 static enum window_copy_cmd_action
   2419 window_copy_cmd_jump_to_backward(struct window_copy_cmd_state *cs)
   2420 {
   2421 	struct window_mode_entry	*wme = cs->wme;
   2422 	struct window_copy_mode_data	*data = wme->data;
   2423 	u_int				 np = wme->prefix;
   2424 	const char			*arg0 = args_string(cs->wargs, 0);
   2425 
   2426 	if (*arg0 != '\0') {
   2427 		data->jumptype = WINDOW_COPY_JUMPTOBACKWARD;
   2428 		free(data->jumpchar);
   2429 		data->jumpchar = utf8_fromcstr(arg0);
   2430 		for (; np != 0; np--)
   2431 			window_copy_cursor_jump_to_back(wme);
   2432 	}
   2433 	return (WINDOW_COPY_CMD_NOTHING);
   2434 }
   2435 
   2436 static enum window_copy_cmd_action
   2437 window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs)
   2438 {
   2439 	struct window_mode_entry	*wme = cs->wme;
   2440 	struct window_copy_mode_data	*data = wme->data;
   2441 	u_int				 np = wme->prefix;
   2442 	const char			*arg0 = args_string(cs->wargs, 0);
   2443 
   2444 	if (*arg0 != '\0') {
   2445 		data->jumptype = WINDOW_COPY_JUMPTOFORWARD;
   2446 		free(data->jumpchar);
   2447 		data->jumpchar = utf8_fromcstr(arg0);
   2448 		for (; np != 0; np--)
   2449 			window_copy_cursor_jump_to(wme);
   2450 	}
   2451 	return (WINDOW_COPY_CMD_NOTHING);
   2452 }
   2453 
   2454 static enum window_copy_cmd_action
   2455 window_copy_cmd_jump_to_mark(struct window_copy_cmd_state *cs)
   2456 {
   2457 	struct window_mode_entry	*wme = cs->wme;
   2458 
   2459 	window_copy_jump_to_mark(wme);
   2460 	return (WINDOW_COPY_CMD_NOTHING);
   2461 }
   2462 
   2463 static enum window_copy_cmd_action
   2464 window_copy_cmd_next_prompt(struct window_copy_cmd_state *cs)
   2465 {
   2466 	struct window_mode_entry	*wme = cs->wme;
   2467 
   2468 	window_copy_cursor_prompt(wme, 1, args_has(cs->wargs, 'o'));
   2469 	return (WINDOW_COPY_CMD_NOTHING);
   2470 }
   2471 
   2472 static enum window_copy_cmd_action
   2473 window_copy_cmd_previous_prompt(struct window_copy_cmd_state *cs)
   2474 {
   2475 	struct window_mode_entry	*wme = cs->wme;
   2476 
   2477 	window_copy_cursor_prompt(wme, 0, args_has(cs->wargs, 'o'));
   2478 	return (WINDOW_COPY_CMD_NOTHING);
   2479 }
   2480 
   2481 static enum window_copy_cmd_action
   2482 window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
   2483 {
   2484 	struct window_mode_entry	*wme = cs->wme;
   2485 	struct window_copy_mode_data	*data = wme->data;
   2486 	u_int				 np = wme->prefix;
   2487 
   2488 	if (!window_copy_expand_search_string(cs))
   2489 		return (WINDOW_COPY_CMD_NOTHING);
   2490 
   2491 	if (data->searchstr != NULL) {
   2492 		data->searchtype = WINDOW_COPY_SEARCHUP;
   2493 		data->searchregex = 1;
   2494 		data->timeout = 0;
   2495 		for (; np != 0; np--)
   2496 			window_copy_search_up(wme, 1);
   2497 	}
   2498 	return (WINDOW_COPY_CMD_NOTHING);
   2499 }
   2500 
   2501 static enum window_copy_cmd_action
   2502 window_copy_cmd_search_backward_text(struct window_copy_cmd_state *cs)
   2503 {
   2504 	struct window_mode_entry	*wme = cs->wme;
   2505 	struct window_copy_mode_data	*data = wme->data;
   2506 	u_int				 np = wme->prefix;
   2507 
   2508 	if (!window_copy_expand_search_string(cs))
   2509 		return (WINDOW_COPY_CMD_NOTHING);
   2510 
   2511 	if (data->searchstr != NULL) {
   2512 		data->searchtype = WINDOW_COPY_SEARCHUP;
   2513 		data->searchregex = 0;
   2514 		data->timeout = 0;
   2515 		for (; np != 0; np--)
   2516 			window_copy_search_up(wme, 0);
   2517 	}
   2518 	return (WINDOW_COPY_CMD_NOTHING);
   2519 }
   2520 
   2521 static enum window_copy_cmd_action
   2522 window_copy_cmd_search_forward(struct window_copy_cmd_state *cs)
   2523 {
   2524 	struct window_mode_entry	*wme = cs->wme;
   2525 	struct window_copy_mode_data	*data = wme->data;
   2526 	u_int				 np = wme->prefix;
   2527 
   2528 	if (!window_copy_expand_search_string(cs))
   2529 		return (WINDOW_COPY_CMD_NOTHING);
   2530 
   2531 	if (data->searchstr != NULL) {
   2532 		data->searchtype = WINDOW_COPY_SEARCHDOWN;
   2533 		data->searchregex = 1;
   2534 		data->timeout = 0;
   2535 		for (; np != 0; np--)
   2536 			window_copy_search_down(wme, 1);
   2537 	}
   2538 	return (WINDOW_COPY_CMD_NOTHING);
   2539 }
   2540 
   2541 static enum window_copy_cmd_action
   2542 window_copy_cmd_search_forward_text(struct window_copy_cmd_state *cs)
   2543 {
   2544 	struct window_mode_entry	*wme = cs->wme;
   2545 	struct window_copy_mode_data	*data = wme->data;
   2546 	u_int				 np = wme->prefix;
   2547 
   2548 	if (!window_copy_expand_search_string(cs))
   2549 		return (WINDOW_COPY_CMD_NOTHING);
   2550 
   2551 	if (data->searchstr != NULL) {
   2552 		data->searchtype = WINDOW_COPY_SEARCHDOWN;
   2553 		data->searchregex = 0;
   2554 		data->timeout = 0;
   2555 		for (; np != 0; np--)
   2556 			window_copy_search_down(wme, 0);
   2557 	}
   2558 	return (WINDOW_COPY_CMD_NOTHING);
   2559 }
   2560 
   2561 static enum window_copy_cmd_action
   2562 window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs)
   2563 {
   2564 	struct window_mode_entry	*wme = cs->wme;
   2565 	struct window_copy_mode_data	*data = wme->data;
   2566 	const char			*arg0 = args_string(cs->wargs, 0);
   2567 	const char			*ss = data->searchstr;
   2568 	char				 prefix;
   2569 	enum window_copy_cmd_action	 action = WINDOW_COPY_CMD_NOTHING;
   2570 
   2571 	data->timeout = 0;
   2572 
   2573 	log_debug("%s: %s", __func__, arg0);
   2574 
   2575 	prefix = *arg0++;
   2576 	if (data->searchx == -1 || data->searchy == -1) {
   2577 		data->searchx = data->cx;
   2578 		data->searchy = data->cy;
   2579 		data->searcho = data->oy;
   2580 	} else if (ss != NULL && strcmp(arg0, ss) != 0) {
   2581 		data->cx = data->searchx;
   2582 		data->cy = data->searchy;
   2583 		data->oy = data->searcho;
   2584 		action = WINDOW_COPY_CMD_REDRAW;
   2585 	}
   2586 	if (*arg0 == '\0') {
   2587 		window_copy_clear_marks(wme);
   2588 		return (WINDOW_COPY_CMD_REDRAW);
   2589 	}
   2590 	switch (prefix) {
   2591 	case '=':
   2592 	case '-':
   2593 		data->searchtype = WINDOW_COPY_SEARCHUP;
   2594 		data->searchregex = 0;
   2595 		free(data->searchstr);
   2596 		data->searchstr = xstrdup(arg0);
   2597 		if (!window_copy_search_up(wme, 0)) {
   2598 			window_copy_clear_marks(wme);
   2599 			return (WINDOW_COPY_CMD_REDRAW);
   2600 		}
   2601 		break;
   2602 	case '+':
   2603 		data->searchtype = WINDOW_COPY_SEARCHDOWN;
   2604 		data->searchregex = 0;
   2605 		free(data->searchstr);
   2606 		data->searchstr = xstrdup(arg0);
   2607 		if (!window_copy_search_down(wme, 0)) {
   2608 			window_copy_clear_marks(wme);
   2609 			return (WINDOW_COPY_CMD_REDRAW);
   2610 		}
   2611 		break;
   2612 	}
   2613 	return (action);
   2614 }
   2615 
   2616 static enum window_copy_cmd_action
   2617 window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
   2618 {
   2619 	struct window_mode_entry	*wme = cs->wme;
   2620 	struct window_copy_mode_data	*data = wme->data;
   2621 	const char			*arg0 = args_string(cs->wargs, 0);
   2622 	const char			*ss = data->searchstr;
   2623 	char				 prefix;
   2624 	enum window_copy_cmd_action	 action = WINDOW_COPY_CMD_NOTHING;
   2625 
   2626 	data->timeout = 0;
   2627 
   2628 	log_debug("%s: %s", __func__, arg0);
   2629 
   2630 	prefix = *arg0++;
   2631 	if (data->searchx == -1 || data->searchy == -1) {
   2632 		data->searchx = data->cx;
   2633 		data->searchy = data->cy;
   2634 		data->searcho = data->oy;
   2635 	} else if (ss != NULL && strcmp(arg0, ss) != 0) {
   2636 		data->cx = data->searchx;
   2637 		data->cy = data->searchy;
   2638 		data->oy = data->searcho;
   2639 		action = WINDOW_COPY_CMD_REDRAW;
   2640 	}
   2641 	if (*arg0 == '\0') {
   2642 		window_copy_clear_marks(wme);
   2643 		return (WINDOW_COPY_CMD_REDRAW);
   2644 	}
   2645 	switch (prefix) {
   2646 	case '=':
   2647 	case '+':
   2648 		data->searchtype = WINDOW_COPY_SEARCHDOWN;
   2649 		data->searchregex = 0;
   2650 		free(data->searchstr);
   2651 		data->searchstr = xstrdup(arg0);
   2652 		if (!window_copy_search_down(wme, 0)) {
   2653 			window_copy_clear_marks(wme);
   2654 			return (WINDOW_COPY_CMD_REDRAW);
   2655 		}
   2656 		break;
   2657 	case '-':
   2658 		data->searchtype = WINDOW_COPY_SEARCHUP;
   2659 		data->searchregex = 0;
   2660 		free(data->searchstr);
   2661 		data->searchstr = xstrdup(arg0);
   2662 		if (!window_copy_search_up(wme, 0)) {
   2663 			window_copy_clear_marks(wme);
   2664 			return (WINDOW_COPY_CMD_REDRAW);
   2665 		}
   2666 	}
   2667 	return (action);
   2668 }
   2669 
   2670 static enum window_copy_cmd_action
   2671 window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs)
   2672 {
   2673 	struct window_mode_entry	*wme = cs->wme;
   2674 	struct window_pane		*wp = wme->swp;
   2675 	struct window_copy_mode_data	*data = wme->data;
   2676 
   2677 	if (data->viewmode)
   2678 		return (WINDOW_COPY_CMD_NOTHING);
   2679 
   2680 	screen_free(data->backing);
   2681 	free(data->backing);
   2682 	data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL,
   2683 	    NULL, wme->swp != wme->wp);
   2684 
   2685 	window_copy_size_changed(wme);
   2686 	return (WINDOW_COPY_CMD_REDRAW);
   2687 }
   2688 
   2689 static const struct {
   2690 	const char			 *command;
   2691 	u_int				  minargs;
   2692 	u_int				  maxargs;
   2693 	struct args_parse		  args;
   2694 	enum window_copy_cmd_clear	  clear;
   2695 	enum window_copy_cmd_action	(*f)(struct window_copy_cmd_state *);
   2696 } window_copy_cmd_table[] = {
   2697 	{ .command = "append-selection",
   2698 	  .args = { "", 0, 0, NULL },
   2699 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2700 	  .f = window_copy_cmd_append_selection
   2701 	},
   2702 	{ .command = "append-selection-and-cancel",
   2703 	  .args = { "", 0, 0, NULL },
   2704 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2705 	  .f = window_copy_cmd_append_selection_and_cancel
   2706 	},
   2707 	{ .command = "back-to-indentation",
   2708 	  .args = { "", 0, 0, NULL },
   2709 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2710 	  .f = window_copy_cmd_back_to_indentation
   2711 	},
   2712 	{ .command = "begin-selection",
   2713 	  .args = { "", 0, 0, NULL },
   2714 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2715 	  .f = window_copy_cmd_begin_selection
   2716 	},
   2717 	{ .command = "bottom-line",
   2718 	  .args = { "", 0, 0, NULL },
   2719 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2720 	  .f = window_copy_cmd_bottom_line
   2721 	},
   2722 	{ .command = "cancel",
   2723 	  .args = { "", 0, 0, NULL },
   2724 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2725 	  .f = window_copy_cmd_cancel
   2726 	},
   2727 	{ .command = "clear-selection",
   2728 	  .args = { "", 0, 0, NULL },
   2729 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2730 	  .f = window_copy_cmd_clear_selection
   2731 	},
   2732 	{ .command = "copy-end-of-line",
   2733 	  .args = { "CP", 0, 1, NULL },
   2734 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2735 	  .f = window_copy_cmd_copy_end_of_line
   2736 	},
   2737 	{ .command = "copy-end-of-line-and-cancel",
   2738 	  .args = { "CP", 0, 1, NULL },
   2739 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2740 	  .f = window_copy_cmd_copy_end_of_line_and_cancel
   2741 	},
   2742 	{ .command = "copy-pipe-end-of-line",
   2743 	  .args = { "CP", 0, 2, NULL },
   2744 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2745 	  .f = window_copy_cmd_copy_pipe_end_of_line
   2746 	},
   2747 	{ .command = "copy-pipe-end-of-line-and-cancel",
   2748 	  .args = { "CP", 0, 2, NULL },
   2749 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2750 	  .f = window_copy_cmd_copy_pipe_end_of_line_and_cancel
   2751 	},
   2752 	{ .command = "copy-line",
   2753 	  .args = { "CP", 0, 1, NULL },
   2754 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2755 	  .f = window_copy_cmd_copy_line
   2756 	},
   2757 	{ .command = "copy-line-and-cancel",
   2758 	  .args = { "CP", 0, 1, NULL },
   2759 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2760 	  .f = window_copy_cmd_copy_line_and_cancel
   2761 	},
   2762 	{ .command = "copy-pipe-line",
   2763 	  .args = { "CP", 0, 2, NULL },
   2764 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2765 	  .f = window_copy_cmd_copy_pipe_line
   2766 	},
   2767 	{ .command = "copy-pipe-line-and-cancel",
   2768 	  .args = { "CP", 0, 2, NULL },
   2769 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2770 	  .f = window_copy_cmd_copy_pipe_line_and_cancel
   2771 	},
   2772 	{ .command = "copy-pipe-no-clear",
   2773 	  .args = { "CP", 0, 2, NULL },
   2774 	  .clear = WINDOW_COPY_CMD_CLEAR_NEVER,
   2775 	  .f = window_copy_cmd_copy_pipe_no_clear
   2776 	},
   2777 	{ .command = "copy-pipe",
   2778 	  .args = { "CP", 0, 2, NULL },
   2779 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2780 	  .f = window_copy_cmd_copy_pipe
   2781 	},
   2782 	{ .command = "copy-pipe-and-cancel",
   2783 	  .args = { "CP", 0, 2, NULL },
   2784 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2785 	  .f = window_copy_cmd_copy_pipe_and_cancel
   2786 	},
   2787 	{ .command = "copy-selection-no-clear",
   2788 	  .args = { "CP", 0, 1, NULL },
   2789 	  .clear = WINDOW_COPY_CMD_CLEAR_NEVER,
   2790 	  .f = window_copy_cmd_copy_selection_no_clear
   2791 	},
   2792 	{ .command = "copy-selection",
   2793 	  .args = { "CP", 0, 1, NULL },
   2794 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2795 	  .f = window_copy_cmd_copy_selection
   2796 	},
   2797 	{ .command = "copy-selection-and-cancel",
   2798 	  .args = { "CP", 0, 1, NULL },
   2799 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2800 	  .f = window_copy_cmd_copy_selection_and_cancel
   2801 	},
   2802 	{ .command = "cursor-down",
   2803 	  .args = { "", 0, 0, NULL },
   2804 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2805 	  .f = window_copy_cmd_cursor_down
   2806 	},
   2807 	{ .command = "cursor-down-and-cancel",
   2808 	  .args = { "", 0, 0, NULL },
   2809 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2810 	  .f = window_copy_cmd_cursor_down_and_cancel
   2811 	},
   2812 	{ .command = "cursor-left",
   2813 	  .args = { "", 0, 0, NULL },
   2814 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2815 	  .f = window_copy_cmd_cursor_left
   2816 	},
   2817 	{ .command = "cursor-right",
   2818 	  .args = { "", 0, 0, NULL },
   2819 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2820 	  .f = window_copy_cmd_cursor_right
   2821 	},
   2822 	{ .command = "cursor-up",
   2823 	  .args = { "", 0, 0, NULL },
   2824 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2825 	  .f = window_copy_cmd_cursor_up
   2826 	},
   2827 	{ .command = "cursor-centre-vertical",
   2828 	  .args = { "", 0, 0, NULL },
   2829 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2830 	  .f = window_copy_cmd_centre_vertical,
   2831 	},
   2832 	{ .command = "cursor-centre-horizontal",
   2833 	  .args = { "", 0, 0, NULL },
   2834 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2835 	  .f = window_copy_cmd_centre_horizontal,
   2836 	},
   2837 	{ .command = "end-of-line",
   2838 	  .args = { "", 0, 0, NULL },
   2839 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2840 	  .f = window_copy_cmd_end_of_line
   2841 	},
   2842 	{ .command = "goto-line",
   2843 	  .args = { "", 1, 1, NULL },
   2844 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2845 	  .f = window_copy_cmd_goto_line
   2846 	},
   2847 	{ .command = "halfpage-down",
   2848 	  .args = { "", 0, 0, NULL },
   2849 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2850 	  .f = window_copy_cmd_halfpage_down
   2851 	},
   2852 	{ .command = "halfpage-down-and-cancel",
   2853 	  .args = { "", 0, 0, NULL },
   2854 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2855 	  .f = window_copy_cmd_halfpage_down_and_cancel
   2856 	},
   2857 	{ .command = "halfpage-up",
   2858 	  .args = { "", 0, 0, NULL },
   2859 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2860 	  .f = window_copy_cmd_halfpage_up
   2861 	},
   2862 	{ .command = "history-bottom",
   2863 	  .args = { "", 0, 0, NULL },
   2864 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2865 	  .f = window_copy_cmd_history_bottom
   2866 	},
   2867 	{ .command = "history-top",
   2868 	  .args = { "", 0, 0, NULL },
   2869 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2870 	  .f = window_copy_cmd_history_top
   2871 	},
   2872 	{ .command = "jump-again",
   2873 	  .args = { "", 0, 0, NULL },
   2874 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2875 	  .f = window_copy_cmd_jump_again
   2876 	},
   2877 	{ .command = "jump-backward",
   2878 	  .args = { "", 1, 1, NULL },
   2879 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2880 	  .f = window_copy_cmd_jump_backward
   2881 	},
   2882 	{ .command = "jump-forward",
   2883 	  .args = { "", 1, 1, NULL },
   2884 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2885 	  .f = window_copy_cmd_jump_forward
   2886 	},
   2887 	{ .command = "jump-reverse",
   2888 	  .args = { "", 0, 0, NULL },
   2889 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2890 	  .f = window_copy_cmd_jump_reverse
   2891 	},
   2892 	{ .command = "jump-to-backward",
   2893 	  .args = { "", 1, 1, NULL },
   2894 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2895 	  .f = window_copy_cmd_jump_to_backward
   2896 	},
   2897 	{ .command = "jump-to-forward",
   2898 	  .args = { "", 1, 1, NULL },
   2899 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2900 	  .f = window_copy_cmd_jump_to_forward
   2901 	},
   2902 	{ .command = "jump-to-mark",
   2903 	  .args = { "", 0, 0, NULL },
   2904 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2905 	  .f = window_copy_cmd_jump_to_mark
   2906 	},
   2907 	{ .command = "next-prompt",
   2908 	  .args = { "o", 0, 0, NULL },
   2909 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2910 	  .f = window_copy_cmd_next_prompt
   2911 	},
   2912 	{ .command = "previous-prompt",
   2913 	  .args = { "o", 0, 0, NULL },
   2914 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2915 	  .f = window_copy_cmd_previous_prompt
   2916 	},
   2917 	{ .command = "middle-line",
   2918 	  .args = { "", 0, 0, NULL },
   2919 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2920 	  .f = window_copy_cmd_middle_line
   2921 	},
   2922 	{ .command = "next-matching-bracket",
   2923 	  .args = { "", 0, 0, NULL },
   2924 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2925 	  .f = window_copy_cmd_next_matching_bracket
   2926 	},
   2927 	{ .command = "next-paragraph",
   2928 	  .args = { "", 0, 0, NULL },
   2929 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2930 	  .f = window_copy_cmd_next_paragraph
   2931 	},
   2932 	{ .command = "next-space",
   2933 	  .args = { "", 0, 0, NULL },
   2934 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2935 	  .f = window_copy_cmd_next_space
   2936 	},
   2937 	{ .command = "next-space-end",
   2938 	  .args = { "", 0, 0, NULL },
   2939 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2940 	  .f = window_copy_cmd_next_space_end
   2941 	},
   2942 	{ .command = "next-word",
   2943 	  .args = { "", 0, 0, NULL },
   2944 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2945 	  .f = window_copy_cmd_next_word
   2946 	},
   2947 	{ .command = "next-word-end",
   2948 	  .args = { "", 0, 0, NULL },
   2949 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2950 	  .f = window_copy_cmd_next_word_end
   2951 	},
   2952 	{ .command = "other-end",
   2953 	  .args = { "", 0, 0, NULL },
   2954 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2955 	  .f = window_copy_cmd_other_end
   2956 	},
   2957 	{ .command = "page-down",
   2958 	  .args = { "", 0, 0, NULL },
   2959 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2960 	  .f = window_copy_cmd_page_down
   2961 	},
   2962 	{ .command = "page-down-and-cancel",
   2963 	  .args = { "", 0, 0, NULL },
   2964 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2965 	  .f = window_copy_cmd_page_down_and_cancel
   2966 	},
   2967 	{ .command = "page-up",
   2968 	  .args = { "", 0, 0, NULL },
   2969 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2970 	  .f = window_copy_cmd_page_up
   2971 	},
   2972 	{ .command = "pipe-no-clear",
   2973 	  .args = { "", 0, 1, NULL },
   2974 	  .clear = WINDOW_COPY_CMD_CLEAR_NEVER,
   2975 	  .f = window_copy_cmd_pipe_no_clear
   2976 	},
   2977 	{ .command = "pipe",
   2978 	  .args = { "", 0, 1, NULL },
   2979 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2980 	  .f = window_copy_cmd_pipe
   2981 	},
   2982 	{ .command = "pipe-and-cancel",
   2983 	  .args = { "", 0, 1, NULL },
   2984 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2985 	  .f = window_copy_cmd_pipe_and_cancel
   2986 	},
   2987 	{ .command = "previous-matching-bracket",
   2988 	  .args = { "", 0, 0, NULL },
   2989 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   2990 	  .f = window_copy_cmd_previous_matching_bracket
   2991 	},
   2992 	{ .command = "previous-paragraph",
   2993 	  .args = { "", 0, 0, NULL },
   2994 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   2995 	  .f = window_copy_cmd_previous_paragraph
   2996 	},
   2997 	{ .command = "previous-space",
   2998 	  .args = { "", 0, 0, NULL },
   2999 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3000 	  .f = window_copy_cmd_previous_space
   3001 	},
   3002 	{ .command = "previous-word",
   3003 	  .args = { "", 0, 0, NULL },
   3004 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3005 	  .f = window_copy_cmd_previous_word
   3006 	},
   3007 	{ .command = "rectangle-on",
   3008 	  .args = { "", 0, 0, NULL },
   3009 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3010 	  .f = window_copy_cmd_rectangle_on
   3011 	},
   3012 	{ .command = "rectangle-off",
   3013 	  .args = { "", 0, 0, NULL },
   3014 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3015 	  .f = window_copy_cmd_rectangle_off
   3016 	},
   3017 	{ .command = "rectangle-toggle",
   3018 	  .args = { "", 0, 0, NULL },
   3019 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3020 	  .f = window_copy_cmd_rectangle_toggle
   3021 	},
   3022 	{ .command = "refresh-from-pane",
   3023 	  .args = { "", 0, 0, NULL },
   3024 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3025 	  .f = window_copy_cmd_refresh_from_pane
   3026 	},
   3027 	{ .command = "scroll-bottom",
   3028 	  .args = { "", 0, 0, NULL },
   3029 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3030 	  .f = window_copy_cmd_scroll_bottom
   3031 	},
   3032 	{ .command = "scroll-down",
   3033 	  .args = { "", 0, 0, NULL },
   3034 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3035 	  .f = window_copy_cmd_scroll_down
   3036 	},
   3037 	{ .command = "scroll-down-and-cancel",
   3038 	  .args = { "", 0, 0, NULL },
   3039 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3040 	  .f = window_copy_cmd_scroll_down_and_cancel
   3041 	},
   3042 	{ .command = "scroll-middle",
   3043 	  .args = { "", 0, 0, NULL },
   3044 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3045 	  .f = window_copy_cmd_scroll_middle
   3046 	},
   3047 	{ .command = "scroll-top",
   3048 	  .args = { "", 0, 0, NULL },
   3049 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3050 	  .f = window_copy_cmd_scroll_top
   3051 	},
   3052 	{ .command = "scroll-up",
   3053 	  .args = { "", 0, 0, NULL },
   3054 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3055 	  .f = window_copy_cmd_scroll_up
   3056 	},
   3057 	{ .command = "search-again",
   3058 	  .args = { "", 0, 0, NULL },
   3059 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3060 	  .f = window_copy_cmd_search_again
   3061 	},
   3062 	{ .command = "search-backward",
   3063 	  .args = { "", 0, 1, NULL },
   3064 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3065 	  .f = window_copy_cmd_search_backward
   3066 	},
   3067 	{ .command = "search-backward-text",
   3068 	  .args = { "", 0, 1, NULL },
   3069 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3070 	  .f = window_copy_cmd_search_backward_text
   3071 	},
   3072 	{ .command = "search-backward-incremental",
   3073 	  .args = { "", 1, 1, NULL },
   3074 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3075 	  .f = window_copy_cmd_search_backward_incremental
   3076 	},
   3077 	{ .command = "search-forward",
   3078 	  .args = { "", 0, 1, NULL },
   3079 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3080 	  .f = window_copy_cmd_search_forward
   3081 	},
   3082 	{ .command = "search-forward-text",
   3083 	  .args = { "", 0, 1, NULL },
   3084 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3085 	  .f = window_copy_cmd_search_forward_text
   3086 	},
   3087 	{ .command = "search-forward-incremental",
   3088 	  .args = { "", 1, 1, NULL },
   3089 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3090 	  .f = window_copy_cmd_search_forward_incremental
   3091 	},
   3092 	{ .command = "search-reverse",
   3093 	  .args = { "", 0, 0, NULL },
   3094 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3095 	  .f = window_copy_cmd_search_reverse
   3096 	},
   3097 	{ .command = "select-line",
   3098 	  .args = { "", 0, 0, NULL },
   3099 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3100 	  .f = window_copy_cmd_select_line
   3101 	},
   3102 	{ .command = "select-word",
   3103 	  .args = { "", 0, 0, NULL },
   3104 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3105 	  .f = window_copy_cmd_select_word
   3106 	},
   3107 	{ .command = "selection-mode",
   3108 	  .args = { "", 0, 1, NULL },
   3109 	  .clear = 0,
   3110 	  .f = window_copy_cmd_selection_mode
   3111 	},
   3112 	{ .command = "set-mark",
   3113 	  .args = { "", 0, 0, NULL },
   3114 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3115 	  .f = window_copy_cmd_set_mark
   3116 	},
   3117 	{ .command = "start-of-line",
   3118 	  .args = { "", 0, 0, NULL },
   3119 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3120 	  .f = window_copy_cmd_start_of_line
   3121 	},
   3122 	{ .command = "stop-selection",
   3123 	  .args = { "", 0, 0, NULL },
   3124 	  .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
   3125 	  .f = window_copy_cmd_stop_selection
   3126 	},
   3127 	{ .command = "toggle-position",
   3128 	  .args = { "", 0, 0, NULL },
   3129 	  .clear = WINDOW_COPY_CMD_CLEAR_NEVER,
   3130 	  .f = window_copy_cmd_toggle_position
   3131 	},
   3132 	{ .command = "top-line",
   3133 	  .args = { "", 0, 0, NULL },
   3134 	  .clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
   3135 	  .f = window_copy_cmd_top_line
   3136 	}
   3137 };
   3138 
   3139 static void
   3140 window_copy_command(struct window_mode_entry *wme, struct client *c,
   3141     struct session *s, struct winlink *wl, struct args *args,
   3142     struct mouse_event *m)
   3143 {
   3144 	struct window_copy_mode_data	*data = wme->data;
   3145 	struct window_pane		*wp = wme->wp;
   3146 	struct window_copy_cmd_state	 cs;
   3147 	enum window_copy_cmd_action	 action;
   3148 	enum window_copy_cmd_clear	 clear = WINDOW_COPY_CMD_CLEAR_NEVER;
   3149 	const char			*command;
   3150 	u_int				 i, count = args_count(args);
   3151 	int				 keys;
   3152 	char				*error = NULL;
   3153 
   3154 	if (count == 0)
   3155 		return;
   3156 	command = args_string(args, 0);
   3157 
   3158 	if (m != NULL && m->valid && !MOUSE_WHEEL(m->b))
   3159 		window_copy_move_mouse(m);
   3160 
   3161 	cs.wme = wme;
   3162 	cs.args = args;
   3163 	cs.wargs = NULL;
   3164 	cs.m = m;
   3165 
   3166 	cs.c = c;
   3167 	cs.s = s;
   3168 	cs.wl = wl;
   3169 
   3170 	action = WINDOW_COPY_CMD_NOTHING;
   3171 	for (i = 0; i < nitems(window_copy_cmd_table); i++) {
   3172 		if (strcmp(window_copy_cmd_table[i].command, command) == 0) {
   3173 			cs.wargs = args_parse(&window_copy_cmd_table[i].args,
   3174 			    args_values(args), count, &error);
   3175 
   3176 			if (error != NULL) {
   3177 				free(error);
   3178 				error = NULL;
   3179 			}
   3180 			if (cs.wargs == NULL)
   3181 				break;
   3182 
   3183 			clear = window_copy_cmd_table[i].clear;
   3184 			action = window_copy_cmd_table[i].f(&cs);
   3185 			args_free(cs.wargs);
   3186 			cs.wargs = NULL;
   3187 			break;
   3188 		}
   3189 	}
   3190 
   3191 	if (strncmp(command, "search-", 7) != 0 && data->searchmark != NULL) {
   3192 		keys = options_get_number(wp->window->options, "mode-keys");
   3193 		if (clear == WINDOW_COPY_CMD_CLEAR_EMACS_ONLY &&
   3194 		    keys == MODEKEY_VI)
   3195 			clear = WINDOW_COPY_CMD_CLEAR_NEVER;
   3196 		if (clear != WINDOW_COPY_CMD_CLEAR_NEVER) {
   3197 			window_copy_clear_marks(wme);
   3198 			data->searchx = data->searchy = -1;
   3199 		}
   3200 		if (action == WINDOW_COPY_CMD_NOTHING)
   3201 			action = WINDOW_COPY_CMD_REDRAW;
   3202 	}
   3203 	wme->prefix = 1;
   3204 
   3205 	if (action == WINDOW_COPY_CMD_CANCEL)
   3206 		window_pane_reset_mode(wp);
   3207 	else if (action == WINDOW_COPY_CMD_REDRAW)
   3208 		window_copy_redraw_screen(wme);
   3209 }
   3210 
   3211 static void
   3212 window_copy_scroll_to(struct window_mode_entry *wme, u_int px, u_int py,
   3213     int no_redraw)
   3214 {
   3215 	struct window_copy_mode_data	*data = wme->data;
   3216 	struct grid			*gd = data->backing->grid;
   3217 	u_int				 offset, gap;
   3218 
   3219 	data->cx = px;
   3220 
   3221 	if (py >= gd->hsize - data->oy && py < gd->hsize - data->oy + gd->sy)
   3222 		data->cy = py - (gd->hsize - data->oy);
   3223 	else {
   3224 		gap = gd->sy / 4;
   3225 		if (py < gd->sy) {
   3226 			offset = 0;
   3227 			data->cy = py;
   3228 		} else if (py > gd->hsize + gd->sy - gap) {
   3229 			offset = gd->hsize;
   3230 			data->cy = py - gd->hsize;
   3231 		} else {
   3232 			offset = py + gap - gd->sy;
   3233 			data->cy = py - offset;
   3234 		}
   3235 		data->oy = gd->hsize - offset;
   3236 	}
   3237 
   3238 	if (!no_redraw && data->searchmark != NULL && !data->timeout)
   3239 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
   3240 	window_copy_update_selection(wme, 1, 0);
   3241 	if (!no_redraw)
   3242 		window_copy_redraw_screen(wme);
   3243 }
   3244 
   3245 static int
   3246 window_copy_search_compare(struct grid *gd, u_int px, u_int py,
   3247     struct grid *sgd, u_int spx, int cis)
   3248 {
   3249 	struct grid_cell	 gc, sgc;
   3250 	const struct utf8_data	*ud, *sud;
   3251 
   3252 	grid_get_cell(gd, px, py, &gc);
   3253 	ud = &gc.data;
   3254 	grid_get_cell(sgd, spx, 0, &sgc);
   3255 	sud = &sgc.data;
   3256 
   3257 	if (*sud->data == '\t' && sud->size == 1 && gc.flags & GRID_FLAG_TAB)
   3258 		return (1);
   3259 
   3260 	if (ud->size != sud->size || ud->width != sud->width)
   3261 		return (0);
   3262 
   3263 	if (cis && ud->size == 1)
   3264 		return (tolower(ud->data[0]) == sud->data[0]);
   3265 
   3266 	return (memcmp(ud->data, sud->data, ud->size) == 0);
   3267 }
   3268 
   3269 static int
   3270 window_copy_search_lr(struct grid *gd, struct grid *sgd, u_int *ppx, u_int py,
   3271     u_int first, u_int last, int cis)
   3272 {
   3273 	u_int			 ax, bx, px, pywrap, endline, padding;
   3274 	int			 matched;
   3275 	struct grid_line	*gl;
   3276 	struct grid_cell	 gc;
   3277 
   3278 	endline = gd->hsize + gd->sy - 1;
   3279 	for (ax = first; ax < last; ax++) {
   3280 		padding = 0;
   3281 		for (bx = 0; bx < sgd->sx; bx++) {
   3282 			px = ax + bx + padding;
   3283 			pywrap = py;
   3284 			/* Wrap line. */
   3285 			while (px >= gd->sx && pywrap < endline) {
   3286 				gl = grid_get_line(gd, pywrap);
   3287 				if (~gl->flags & GRID_LINE_WRAPPED)
   3288 					break;
   3289 				px -= gd->sx;
   3290 				pywrap++;
   3291 			}
   3292 			/* We have run off the end of the grid. */
   3293 			if (px - padding >= gd->sx)
   3294 				break;
   3295 
   3296 			grid_get_cell(gd, px, pywrap, &gc);
   3297 			if (gc.flags & GRID_FLAG_TAB)
   3298 				padding += gc.data.width - 1;
   3299 
   3300 			matched = window_copy_search_compare(gd, px, pywrap,
   3301 			    sgd, bx, cis);
   3302 			if (!matched)
   3303 				break;
   3304 		}
   3305 		if (bx == sgd->sx) {
   3306 			*ppx = ax;
   3307 			return (1);
   3308 		}
   3309 	}
   3310 	return (0);
   3311 }
   3312 
   3313 static int
   3314 window_copy_search_rl(struct grid *gd,
   3315     struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis)
   3316 {
   3317 	u_int			 ax, bx, px, pywrap, endline, padding;
   3318 	int			 matched;
   3319 	struct grid_line	*gl;
   3320 	struct grid_cell	 gc;
   3321 
   3322 	endline = gd->hsize + gd->sy - 1;
   3323 	for (ax = last; ax > first; ax--) {
   3324 		padding = 0;
   3325 		for (bx = 0; bx < sgd->sx; bx++) {
   3326 			px = ax - 1 + bx + padding;
   3327 			pywrap = py;
   3328 			/* Wrap line. */
   3329 			while (px >= gd->sx && pywrap < endline) {
   3330 				gl = grid_get_line(gd, pywrap);
   3331 				if (~gl->flags & GRID_LINE_WRAPPED)
   3332 					break;
   3333 				px -= gd->sx;
   3334 				pywrap++;
   3335 			}
   3336 			/* We have run off the end of the grid. */
   3337 			if (px - padding >= gd->sx)
   3338 				break;
   3339 
   3340 			grid_get_cell(gd, px, pywrap, &gc);
   3341 			if (gc.flags & GRID_FLAG_TAB)
   3342 				padding += gc.data.width - 1;
   3343 
   3344 			matched = window_copy_search_compare(gd, px, pywrap,
   3345 			    sgd, bx, cis);
   3346 			if (!matched)
   3347 				break;
   3348 		}
   3349 		if (bx == sgd->sx) {
   3350 			*ppx = ax - 1;
   3351 			return (1);
   3352 		}
   3353 	}
   3354 	return (0);
   3355 }
   3356 
   3357 static int
   3358 window_copy_search_lr_regex(struct grid *gd, u_int *ppx, u_int *psx, u_int py,
   3359     u_int first, u_int last, regex_t *reg)
   3360 {
   3361 	int			eflags = 0;
   3362 	u_int			endline, foundx, foundy, len, pywrap, size = 1;
   3363 	char		       *buf;
   3364 	regmatch_t		regmatch;
   3365 	struct grid_line       *gl;
   3366 
   3367 	/*
   3368 	 * This can happen during search if the last match was the last
   3369 	 * character on a line.
   3370 	 */
   3371 	if (first >= last)
   3372 		return (0);
   3373 
   3374 	/* Set flags for regex search. */
   3375 	if (first != 0)
   3376 		eflags |= REG_NOTBOL;
   3377 
   3378 	/* Need to look at the entire string. */
   3379 	buf = xmalloc(size);
   3380 	buf[0] = '\0';
   3381 	buf = window_copy_stringify(gd, py, first, gd->sx, buf, &size);
   3382 	len = gd->sx - first;
   3383 	endline = gd->hsize + gd->sy - 1;
   3384 	pywrap = py;
   3385 	while (buf != NULL &&
   3386 	    pywrap <= endline &&
   3387 	    len < WINDOW_COPY_SEARCH_MAX_LINE) {
   3388 		gl = grid_get_line(gd, pywrap);
   3389 		if (~gl->flags & GRID_LINE_WRAPPED)
   3390 			break;
   3391 		pywrap++;
   3392 		buf = window_copy_stringify(gd, pywrap, 0, gd->sx, buf, &size);
   3393 		len += gd->sx;
   3394 	}
   3395 
   3396 	if (regexec(reg, buf, 1, &regmatch, eflags) == 0 &&
   3397 	    regmatch.rm_so != regmatch.rm_eo) {
   3398 		foundx = first;
   3399 		foundy = py;
   3400 		window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
   3401 		    buf + regmatch.rm_so);
   3402 		if (foundy == py && foundx < last) {
   3403 			*ppx = foundx;
   3404 			len -= foundx - first;
   3405 			window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
   3406 			    buf + regmatch.rm_eo);
   3407 			*psx = foundx;
   3408 			while (foundy > py) {
   3409 				*psx += gd->sx;
   3410 				foundy--;
   3411 			}
   3412 			*psx -= *ppx;
   3413 			free(buf);
   3414 			return (1);
   3415 		}
   3416 	}
   3417 
   3418 	free(buf);
   3419 	*ppx = 0;
   3420 	*psx = 0;
   3421 	return (0);
   3422 }
   3423 
   3424 static int
   3425 window_copy_search_rl_regex(struct grid *gd, u_int *ppx, u_int *psx, u_int py,
   3426     u_int first, u_int last, regex_t *reg)
   3427 {
   3428 	int			eflags = 0;
   3429 	u_int			endline, len, pywrap, size = 1;
   3430 	char		       *buf;
   3431 	struct grid_line       *gl;
   3432 
   3433 	/* Set flags for regex search. */
   3434 	if (first != 0)
   3435 		eflags |= REG_NOTBOL;
   3436 
   3437 	/* Need to look at the entire string. */
   3438 	buf = xmalloc(size);
   3439 	buf[0] = '\0';
   3440 	buf = window_copy_stringify(gd, py, first, gd->sx, buf, &size);
   3441 	len = gd->sx - first;
   3442 	endline = gd->hsize + gd->sy - 1;
   3443 	pywrap = py;
   3444 	while (buf != NULL &&
   3445 	    pywrap <= endline &&
   3446 	    len < WINDOW_COPY_SEARCH_MAX_LINE) {
   3447 		gl = grid_get_line(gd, pywrap);
   3448 		if (~gl->flags & GRID_LINE_WRAPPED)
   3449 			break;
   3450 		pywrap++;
   3451 		buf = window_copy_stringify(gd, pywrap, 0, gd->sx, buf, &size);
   3452 		len += gd->sx;
   3453 	}
   3454 
   3455 	if (window_copy_last_regex(gd, py, first, last, len, ppx, psx, buf,
   3456 	    reg, eflags))
   3457 	{
   3458 		free(buf);
   3459 		return (1);
   3460 	}
   3461 
   3462 	free(buf);
   3463 	*ppx = 0;
   3464 	*psx = 0;
   3465 	return (0);
   3466 }
   3467 
   3468 static const char *
   3469 window_copy_cellstring(const struct grid_line *gl, u_int px, size_t *size,
   3470     int *allocated)
   3471 {
   3472 	static struct utf8_data	 ud;
   3473 	struct grid_cell_entry	*gce;
   3474 	char			*copy;
   3475 
   3476 	if (px >= gl->cellsize) {
   3477 		*size = 1;
   3478 		*allocated = 0;
   3479 		return (" ");
   3480 	}
   3481 
   3482 	gce = &gl->celldata[px];
   3483 	if (gce->flags & GRID_FLAG_PADDING) {
   3484 		*size = 0;
   3485 		*allocated = 0;
   3486 		return (NULL);
   3487 	}
   3488 	if (~gce->flags & GRID_FLAG_EXTENDED) {
   3489 		*size = 1;
   3490 		*allocated = 0;
   3491 		return (const char *)(&gce->data.data);
   3492 	}
   3493 	if (gce->flags & GRID_FLAG_TAB) {
   3494 		*size = 1;
   3495 		*allocated = 0;
   3496 		return ("\t");
   3497 	}
   3498 
   3499 	utf8_to_data(gl->extddata[gce->offset].data, &ud);
   3500 	if (ud.size == 0) {
   3501 		*size = 0;
   3502 		*allocated = 0;
   3503 		return (NULL);
   3504 	}
   3505 	*size = ud.size;
   3506 	*allocated = 1;
   3507 
   3508 	copy = xmalloc(ud.size);
   3509 	memcpy(copy, ud.data, ud.size);
   3510 	return (copy);
   3511 }
   3512 
   3513 /* Find last match in given range. */
   3514 static int
   3515 window_copy_last_regex(struct grid *gd, u_int py, u_int first, u_int last,
   3516     u_int len, u_int *ppx, u_int *psx, const char *buf, const regex_t *preg,
   3517     int eflags)
   3518 {
   3519 	u_int		foundx, foundy, oldx, px = 0, savepx, savesx = 0;
   3520 	regmatch_t	regmatch;
   3521 
   3522 	foundx = first;
   3523 	foundy = py;
   3524 	oldx = first;
   3525 	while (regexec(preg, buf + px, 1, &regmatch, eflags) == 0) {
   3526 		if (regmatch.rm_so == regmatch.rm_eo)
   3527 			break;
   3528 		window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
   3529 		    buf + px + regmatch.rm_so);
   3530 		if (foundy > py || foundx >= last)
   3531 			break;
   3532 		len -= foundx - oldx;
   3533 		savepx = foundx;
   3534 		window_copy_cstrtocellpos(gd, len, &foundx, &foundy,
   3535 		    buf + px + regmatch.rm_eo);
   3536 		if (foundy > py || foundx >= last) {
   3537 			*ppx = savepx;
   3538 			*psx = foundx;
   3539 			while (foundy > py) {
   3540 				*psx += gd->sx;
   3541 				foundy--;
   3542 			}
   3543 			*psx -= *ppx;
   3544 			return (1);
   3545 		} else {
   3546 			savesx = foundx - savepx;
   3547 			len -= savesx;
   3548 			oldx = foundx;
   3549 		}
   3550 		px += regmatch.rm_eo;
   3551 	}
   3552 
   3553 	if (savesx > 0) {
   3554 		*ppx = savepx;
   3555 		*psx = savesx;
   3556 		return (1);
   3557 	} else {
   3558 		*ppx = 0;
   3559 		*psx = 0;
   3560 		return (0);
   3561 	}
   3562 }
   3563 
   3564 /* Stringify line and append to input buffer. Caller frees. */
   3565 static char *
   3566 window_copy_stringify(struct grid *gd, u_int py, u_int first, u_int last,
   3567     char *buf, u_int *size)
   3568 {
   3569 	u_int			 ax, bx, newsize = *size;
   3570 	const struct grid_line	*gl;
   3571 	const char		*d;
   3572 	size_t			 bufsize = 1024, dlen;
   3573 	int			 allocated;
   3574 
   3575 	while (bufsize < newsize)
   3576 		bufsize *= 2;
   3577 	buf = xrealloc(buf, bufsize);
   3578 
   3579 	gl = grid_peek_line(gd, py);
   3580 	bx = *size - 1;
   3581 	for (ax = first; ax < last; ax++) {
   3582 		d = window_copy_cellstring(gl, ax, &dlen, &allocated);
   3583 		newsize += dlen;
   3584 		while (bufsize < newsize) {
   3585 			bufsize *= 2;
   3586 			buf = xrealloc(buf, bufsize);
   3587 		}
   3588 		if (dlen == 1)
   3589 			buf[bx++] = *d;
   3590 		else {
   3591 			memcpy(buf + bx, d, dlen);
   3592 			bx += dlen;
   3593 		}
   3594 		if (allocated)
   3595 			free(__UNCONST(d));
   3596 	}
   3597 	buf[newsize - 1] = '\0';
   3598 
   3599 	*size = newsize;
   3600 	return (buf);
   3601 }
   3602 
   3603 /* Map start of C string containing UTF-8 data to grid cell position. */
   3604 static void
   3605 window_copy_cstrtocellpos(struct grid *gd, u_int ncells, u_int *ppx, u_int *ppy,
   3606     const char *str)
   3607 {
   3608 	u_int			 cell, ccell, px, pywrap, pos, len;
   3609 	int			 match;
   3610 	const struct grid_line	*gl;
   3611 	const char		*d;
   3612 	size_t			 dlen;
   3613 	struct {
   3614 		const char	*d;
   3615 		size_t		 dlen;
   3616 		int		 allocated;
   3617 	} *cells;
   3618 
   3619 	/* Populate the array of cell data. */
   3620 	cells = xreallocarray(NULL, ncells, sizeof cells[0]);
   3621 	cell = 0;
   3622 	px = *ppx;
   3623 	pywrap = *ppy;
   3624 	gl = grid_peek_line(gd, pywrap);
   3625 	while (cell < ncells) {
   3626 		cells[cell].d = window_copy_cellstring(gl, px,
   3627 		    &cells[cell].dlen, &cells[cell].allocated);
   3628 		cell++;
   3629 		px++;
   3630 		if (px == gd->sx) {
   3631 			px = 0;
   3632 			pywrap++;
   3633 			gl = grid_peek_line(gd, pywrap);
   3634 		}
   3635 	}
   3636 
   3637 	/* Locate starting cell. */
   3638 	cell = 0;
   3639 	len = strlen(str);
   3640 	while (cell < ncells) {
   3641 		ccell = cell;
   3642 		pos = 0;
   3643 		match = 1;
   3644 		while (ccell < ncells) {
   3645 			if (str[pos] == '\0') {
   3646 				match = 0;
   3647 				break;
   3648 			}
   3649 			d = cells[ccell].d;
   3650 			dlen = cells[ccell].dlen;
   3651 			if (dlen == 1) {
   3652 				if (str[pos] != *d) {
   3653 					match = 0;
   3654 					break;
   3655 				}
   3656 				pos++;
   3657 			} else {
   3658 				if (dlen > len - pos)
   3659 					dlen = len - pos;
   3660 				if (memcmp(str + pos, d, dlen) != 0) {
   3661 					match = 0;
   3662 					break;
   3663 				}
   3664 				pos += dlen;
   3665 			}
   3666 			ccell++;
   3667 		}
   3668 		if (match)
   3669 			break;
   3670 		cell++;
   3671 	}
   3672 
   3673 	/* If not found this will be one past the end. */
   3674 	px = *ppx + cell;
   3675 	pywrap = *ppy;
   3676 	while (px >= gd->sx) {
   3677 		px -= gd->sx;
   3678 		pywrap++;
   3679 	}
   3680 
   3681 	*ppx = px;
   3682 	*ppy = pywrap;
   3683 
   3684 	/* Free cell data. */
   3685 	for (cell = 0; cell < ncells; cell++) {
   3686 		if (cells[cell].allocated)
   3687 			free(__UNCONST(cells[cell].d));
   3688 	}
   3689 	free(cells);
   3690 }
   3691 
   3692 static void
   3693 window_copy_move_left(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
   3694 {
   3695 	if (*fx == 0) {	/* left */
   3696 		if (*fy == 0) { /* top */
   3697 			if (wrapflag) {
   3698 				*fx = screen_size_x(s) - 1;
   3699 				*fy = screen_hsize(s) + screen_size_y(s) - 1;
   3700 			}
   3701 			return;
   3702 		}
   3703 		*fx = screen_size_x(s) - 1;
   3704 		*fy = *fy - 1;
   3705 	} else
   3706 		*fx = *fx - 1;
   3707 }
   3708 
   3709 static void
   3710 window_copy_move_right(struct screen *s, u_int *fx, u_int *fy, int wrapflag)
   3711 {
   3712 	if (*fx == screen_size_x(s) - 1) { /* right */
   3713 		if (*fy == screen_hsize(s) + screen_size_y(s) - 1) { /* bottom */
   3714 			if (wrapflag) {
   3715 				*fx = 0;
   3716 				*fy = 0;
   3717 			}
   3718 			return;
   3719 		}
   3720 		*fx = 0;
   3721 		*fy = *fy + 1;
   3722 	} else
   3723 		*fx = *fx + 1;
   3724 }
   3725 
   3726 static int
   3727 window_copy_is_lowercase(const char *ptr)
   3728 {
   3729 	while (*ptr != '\0') {
   3730 		if (*ptr != tolower((u_char)*ptr))
   3731 			return (0);
   3732 		++ptr;
   3733 	}
   3734 	return (1);
   3735 }
   3736 
   3737 /*
   3738  * Handle backward wrapped regex searches with overlapping matches. In this case
   3739  * find the longest overlapping match from previous wrapped lines.
   3740  */
   3741 static void
   3742 window_copy_search_back_overlap(struct grid *gd, regex_t *preg, u_int *ppx,
   3743     u_int *psx, u_int *ppy, u_int endline)
   3744 {
   3745 	u_int	endx, endy, oldendx, oldendy, px, py, sx;
   3746 	int	found = 1;
   3747 
   3748 	oldendx = *ppx + *psx;
   3749 	oldendy = *ppy - 1;
   3750 	while (oldendx > gd->sx - 1) {
   3751 		oldendx -= gd->sx;
   3752 		oldendy++;
   3753 	}
   3754 	endx = oldendx;
   3755 	endy = oldendy;
   3756 	px = *ppx;
   3757 	py = *ppy;
   3758 	while (found && px == 0 && py - 1 > endline &&
   3759 	       grid_get_line(gd, py - 2)->flags & GRID_LINE_WRAPPED &&
   3760 	       endx == oldendx && endy == oldendy) {
   3761 		py--;
   3762 		found = window_copy_search_rl_regex(gd, &px, &sx, py - 1, 0,
   3763 		    gd->sx, preg);
   3764 		if (found) {
   3765 			endx = px + sx;
   3766 			endy = py - 1;
   3767 			while (endx > gd->sx - 1) {
   3768 				endx -= gd->sx;
   3769 				endy++;
   3770 			}
   3771 			if (endx == oldendx && endy == oldendy) {
   3772 				*ppx = px;
   3773 				*ppy = py;
   3774 			}
   3775 		}
   3776 	}
   3777 }
   3778 
   3779 /*
   3780  * Search for text stored in sgd starting from position fx,fy up to endline. If
   3781  * found, jump to it. If cis then ignore case. The direction is 0 for searching
   3782  * up, down otherwise. If wrap then go to begin/end of grid and try again if
   3783  * not found.
   3784  */
   3785 static int
   3786 window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd,
   3787     struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap,
   3788     int direction, int regex)
   3789 {
   3790 	u_int	 i, px, sx, ssize = 1;
   3791 	int	 found = 0, cflags = REG_EXTENDED;
   3792 	char	*sbuf;
   3793 	regex_t	 reg;
   3794 
   3795 	if (regex) {
   3796 		sbuf = xmalloc(ssize);
   3797 		sbuf[0] = '\0';
   3798 		sbuf = window_copy_stringify(sgd, 0, 0, sgd->sx, sbuf, &ssize);
   3799 		if (cis)
   3800 			cflags |= REG_ICASE;
   3801 		if (regcomp(&reg, sbuf, cflags) != 0) {
   3802 			free(sbuf);
   3803 			return (0);
   3804 		}
   3805 		free(sbuf);
   3806 	}
   3807 
   3808 	if (direction) {
   3809 		for (i = fy; i <= endline; i++) {
   3810 			if (regex) {
   3811 				found = window_copy_search_lr_regex(gd,
   3812 				    &px, &sx, i, fx, gd->sx, &reg);
   3813 			} else {
   3814 				found = window_copy_search_lr(gd, sgd,
   3815 				    &px, i, fx, gd->sx, cis);
   3816 			}
   3817 			if (found)
   3818 				break;
   3819 			fx = 0;
   3820 		}
   3821 	} else {
   3822 		for (i = fy + 1; endline < i; i--) {
   3823 			if (regex) {
   3824 				found = window_copy_search_rl_regex(gd,
   3825 				    &px, &sx, i - 1, 0, fx + 1, &reg);
   3826 				if (found) {
   3827 					window_copy_search_back_overlap(gd,
   3828 					    &reg, &px, &sx, &i, endline);
   3829 				}
   3830 			} else {
   3831 				found = window_copy_search_rl(gd, sgd,
   3832 				    &px, i - 1, 0, fx + 1, cis);
   3833 			}
   3834 			if (found) {
   3835 				i--;
   3836 				break;
   3837 			}
   3838 			fx = gd->sx - 1;
   3839 		}
   3840 	}
   3841 	if (regex)
   3842 		regfree(&reg);
   3843 
   3844 	if (found) {
   3845 		window_copy_scroll_to(wme, px, i, 1);
   3846 		return (1);
   3847 	}
   3848 	if (wrap) {
   3849 		return (window_copy_search_jump(wme, gd, sgd,
   3850 		    direction ? 0 : gd->sx - 1,
   3851 		    direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0,
   3852 		    direction, regex));
   3853 	}
   3854 	return (0);
   3855 }
   3856 
   3857 static void
   3858 window_copy_move_after_search_mark(struct window_copy_mode_data *data,
   3859     u_int *fx, u_int *fy, int wrapflag)
   3860 {
   3861 	struct screen  *s = data->backing;
   3862 	u_int		at, start;
   3863 
   3864 	if (window_copy_search_mark_at(data, *fx, *fy, &start) == 0 &&
   3865 	    data->searchmark[start] != 0) {
   3866 		while (window_copy_search_mark_at(data, *fx, *fy, &at) == 0) {
   3867 			if (data->searchmark[at] != data->searchmark[start])
   3868 				break;
   3869 			/* Stop if not wrapping and at the end of the grid. */
   3870 			if (!wrapflag &&
   3871 			    *fx == screen_size_x(s) - 1 &&
   3872 			    *fy == screen_hsize(s) + screen_size_y(s) - 1)
   3873 				break;
   3874 
   3875 			window_copy_move_right(s, fx, fy, wrapflag);
   3876 		}
   3877 	}
   3878 }
   3879 
   3880 /*
   3881  * Search in for text searchstr. If direction is 0 then search up, otherwise
   3882  * down.
   3883  */
   3884 static int
   3885 window_copy_search(struct window_mode_entry *wme, int direction, int regex)
   3886 {
   3887 	struct window_pane		*wp = wme->wp;
   3888 	struct window_copy_mode_data	*data = wme->data;
   3889 	struct screen			*s = data->backing, ss;
   3890 	struct screen_write_ctx		 ctx;
   3891 	struct grid			*gd = s->grid;
   3892 	const char			*str = data->searchstr;
   3893 	u_int				 at, endline, fx, fy, start, ssx;
   3894 	int				 cis, found, keys, visible_only;
   3895 	int				 wrapflag;
   3896 
   3897 	if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0')
   3898 		regex = 0;
   3899 
   3900 	data->searchdirection = direction;
   3901 
   3902 	if (data->timeout)
   3903 		return (0);
   3904 
   3905 	if (data->searchall || wp->searchstr == NULL ||
   3906 	    wp->searchregex != regex) {
   3907 		visible_only = 0;
   3908 		data->searchall = 0;
   3909 	} else
   3910 		visible_only = (strcmp(wp->searchstr, str) == 0);
   3911 	if (visible_only == 0 && data->searchmark != NULL)
   3912 		window_copy_clear_marks(wme);
   3913 	free(wp->searchstr);
   3914 	wp->searchstr = xstrdup(str);
   3915 	wp->searchregex = regex;
   3916 
   3917 	fx = data->cx;
   3918 	fy = screen_hsize(data->backing) - data->oy + data->cy;
   3919 
   3920 	if ((ssx = screen_write_strlen("%s", str)) == 0)
   3921 		return (0);
   3922 	screen_init(&ss, ssx, 1, 0);
   3923 	screen_write_start(&ctx, &ss);
   3924 	screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", str);
   3925 	screen_write_stop(&ctx);
   3926 
   3927 	wrapflag = options_get_number(wp->window->options, "wrap-search");
   3928 	cis = window_copy_is_lowercase(str);
   3929 
   3930 	keys = options_get_number(wp->window->options, "mode-keys");
   3931 
   3932 	if (direction) {
   3933 		/*
   3934 		 * Behave according to mode-keys. If it is emacs, search forward
   3935 		 * leaves the cursor after the match. If it is vi, the cursor
   3936 		 * remains at the beginning of the match, regardless of
   3937 		 * direction, which means that we need to start the next search
   3938 		 * after the term the cursor is currently on when searching
   3939 		 * forward.
   3940 		 */
   3941 		if (keys == MODEKEY_VI) {
   3942 			if (data->searchmark != NULL)
   3943 				window_copy_move_after_search_mark(data, &fx,
   3944 				    &fy, wrapflag);
   3945 			else {
   3946 				/*
   3947 				 * When there are no search marks, start the
   3948 				 * search after the current cursor position.
   3949 				 */
   3950 				window_copy_move_right(s, &fx, &fy, wrapflag);
   3951 			}
   3952 		}
   3953 		endline = gd->hsize + gd->sy - 1;
   3954 	} else {
   3955 		window_copy_move_left(s, &fx, &fy, wrapflag);
   3956 		endline = 0;
   3957 	}
   3958 
   3959 	found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis,
   3960 	    wrapflag, direction, regex);
   3961 	if (found) {
   3962 		window_copy_search_marks(wme, &ss, regex, visible_only);
   3963 		fx = data->cx;
   3964 		fy = screen_hsize(data->backing) - data->oy + data->cy;
   3965 
   3966 		/*
   3967 		 * When searching forward, if the cursor is not at the beginning
   3968 		 * of the mark, search again.
   3969 		 */
   3970 		if (direction &&
   3971 		    window_copy_search_mark_at(data, fx, fy, &at) == 0 &&
   3972 		    at > 0 &&
   3973 		    data->searchmark != NULL &&
   3974 		    data->searchmark[at] == data->searchmark[at - 1]) {
   3975 			window_copy_move_after_search_mark(data, &fx, &fy,
   3976 			    wrapflag);
   3977 			window_copy_search_jump(wme, gd, ss.grid, fx,
   3978 			    fy, endline, cis, wrapflag, direction,
   3979 			    regex);
   3980 			fx = data->cx;
   3981 			fy = screen_hsize(data->backing) - data->oy + data->cy;
   3982 		}
   3983 
   3984 		if (direction) {
   3985 			/*
   3986 			 * When in Emacs mode, position the cursor just after
   3987 			 * the mark.
   3988 			 */
   3989 			if (keys == MODEKEY_EMACS) {
   3990 				window_copy_move_after_search_mark(data, &fx,
   3991 				    &fy, wrapflag);
   3992 				data->cx = fx;
   3993 				data->cy = fy - screen_hsize(data->backing) +
   3994 				    data-> oy;
   3995 			}
   3996 		} else {
   3997 			/*
   3998 			 * When searching backward, position the cursor at the
   3999 			 * beginning of the mark.
   4000 			 */
   4001 			if (window_copy_search_mark_at(data, fx, fy,
   4002 			        &start) == 0) {
   4003 				while (window_copy_search_mark_at(data, fx, fy,
   4004 				           &at) == 0 &&
   4005 				       data->searchmark != NULL &&
   4006 				       data->searchmark[at] ==
   4007 				           data->searchmark[start]) {
   4008 					data->cx = fx;
   4009 					data->cy = fy -
   4010 					    screen_hsize(data->backing) +
   4011 					    data-> oy;
   4012 					if (at == 0)
   4013 						break;
   4014 
   4015 					window_copy_move_left(s, &fx, &fy, 0);
   4016 				}
   4017 			}
   4018 		}
   4019 	}
   4020 	window_copy_redraw_screen(wme);
   4021 
   4022 	screen_free(&ss);
   4023 	return (found);
   4024 }
   4025 
   4026 static void
   4027 window_copy_visible_lines(struct window_copy_mode_data *data, u_int *start,
   4028     u_int *end)
   4029 {
   4030 	struct grid		*gd = data->backing->grid;
   4031 	const struct grid_line	*gl;
   4032 
   4033 	for (*start = gd->hsize - data->oy; *start > 0; (*start)--) {
   4034 		gl = grid_peek_line(gd, (*start) - 1);
   4035 		if (~gl->flags & GRID_LINE_WRAPPED)
   4036 			break;
   4037 	}
   4038 	*end = gd->hsize - data->oy + gd->sy;
   4039 }
   4040 
   4041 static int
   4042 window_copy_search_mark_at(struct window_copy_mode_data *data, u_int px,
   4043     u_int py, u_int *at)
   4044 {
   4045 	struct screen	*s = data->backing;
   4046 	struct grid	*gd = s->grid;
   4047 
   4048 	if (py < gd->hsize - data->oy)
   4049 		return (-1);
   4050 	if (py > gd->hsize - data->oy + gd->sy - 1)
   4051 		return (-1);
   4052 	*at = ((py - (gd->hsize - data->oy)) * gd->sx) + px;
   4053 	return (0);
   4054 }
   4055 
   4056 static u_int
   4057 window_copy_clip_width(u_int width, u_int b, u_int sx, u_int sy)
   4058 {
   4059 	return ((b + width > sx * sy) ? (sx * sy) - b : width);
   4060 }
   4061 
   4062 static u_int
   4063 window_copy_search_mark_match(struct window_copy_mode_data *data, u_int px,
   4064     u_int py, u_int width, int regex)
   4065 {
   4066 	struct grid		*gd = data->backing->grid;
   4067 	struct grid_cell	 gc;
   4068 	u_int			 i, b, w = width, sx = gd->sx, sy = gd->sy;
   4069 
   4070 	if (window_copy_search_mark_at(data, px, py, &b) == 0) {
   4071 		width = window_copy_clip_width(width, b, sx, sy);
   4072 		w = width;
   4073 		for (i = b; i < b + w; i++) {
   4074 			if (!regex) {
   4075 				grid_get_cell(gd, px + (i - b), py, &gc);
   4076 				if (gc.flags & GRID_FLAG_TAB)
   4077 					w += gc.data.width - 1;
   4078 				w = window_copy_clip_width(w, b, sx, sy);
   4079 			}
   4080 			if (data->searchmark[i] != 0)
   4081 				continue;
   4082 			data->searchmark[i] = data->searchgen;
   4083 		}
   4084 		if (data->searchgen == UCHAR_MAX)
   4085 			data->searchgen = 1;
   4086 		else
   4087 			data->searchgen++;
   4088 	}
   4089 
   4090 	return (w);
   4091 }
   4092 
   4093 static int
   4094 window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp,
   4095     int regex, int visible_only)
   4096 {
   4097 	struct window_copy_mode_data	*data = wme->data;
   4098 	struct screen			*s = data->backing, ss;
   4099 	struct screen_write_ctx		 ctx;
   4100 	struct grid			*gd = s->grid;
   4101 	struct grid_cell		 gc;
   4102 	int				 found, cis, stopped = 0;
   4103 	int				 cflags = REG_EXTENDED;
   4104 	u_int				 px, py, nfound = 0, width;
   4105 	u_int				 ssize = 1, start, end, sx = gd->sx;
   4106 	u_int				 sy = gd->sy;
   4107 	char				*sbuf;
   4108 	regex_t				 reg;
   4109 	uint64_t			 stop = 0, tstart, t;
   4110 
   4111 	if (ssp == NULL) {
   4112 		width = screen_write_strlen("%s", data->searchstr);
   4113 		screen_init(&ss, width, 1, 0);
   4114 		screen_write_start(&ctx, &ss);
   4115 		screen_write_nputs(&ctx, -1, &grid_default_cell, "%s",
   4116 		    data->searchstr);
   4117 		screen_write_stop(&ctx);
   4118 		ssp = &ss;
   4119 	} else
   4120 		width = screen_size_x(ssp);
   4121 
   4122 	cis = window_copy_is_lowercase(data->searchstr);
   4123 
   4124 	if (regex) {
   4125 		sbuf = xmalloc(ssize);
   4126 		sbuf[0] = '\0';
   4127 		sbuf = window_copy_stringify(ssp->grid, 0, 0, ssp->grid->sx,
   4128 		    sbuf, &ssize);
   4129 		if (cis)
   4130 			cflags |= REG_ICASE;
   4131 		if (regcomp(&reg, sbuf, cflags) != 0) {
   4132 			free(sbuf);
   4133 			return (0);
   4134 		}
   4135 		free(sbuf);
   4136 	}
   4137 	tstart = get_timer();
   4138 
   4139 	if (visible_only)
   4140 		window_copy_visible_lines(data, &start, &end);
   4141 	else {
   4142 		start = 0;
   4143 		end = gd->hsize + sy;
   4144 		stop = get_timer() + WINDOW_COPY_SEARCH_ALL_TIMEOUT;
   4145 	}
   4146 
   4147 again:
   4148 	free(data->searchmark);
   4149 	data->searchmark = xcalloc(sx, sy);
   4150 	data->searchgen = 1;
   4151 
   4152 	for (py = start; py < end; py++) {
   4153 		px = 0;
   4154 		for (;;) {
   4155 			if (regex) {
   4156 				found = window_copy_search_lr_regex(gd,
   4157 				    &px, &width, py, px, sx, &reg);
   4158 				grid_get_cell(gd, px + width - 1, py, &gc);
   4159 				if (gc.data.width > 2)
   4160 					width += gc.data.width - 1;
   4161 				if (!found)
   4162 					break;
   4163 			} else {
   4164 				found = window_copy_search_lr(gd, ssp->grid,
   4165 				    &px, py, px, sx, cis);
   4166 				if (!found)
   4167 					break;
   4168 			}
   4169 			nfound++;
   4170 			px += window_copy_search_mark_match(data, px, py, width,
   4171 			    regex);
   4172 		}
   4173 
   4174 		t = get_timer();
   4175 		if (t - tstart > WINDOW_COPY_SEARCH_TIMEOUT) {
   4176 			data->timeout = 1;
   4177 			break;
   4178 		}
   4179 		if (stop != 0 && t > stop) {
   4180 			stopped = 1;
   4181 			break;
   4182 		}
   4183 	}
   4184 	if (data->timeout) {
   4185 		window_copy_clear_marks(wme);
   4186 		goto out;
   4187 	}
   4188 
   4189 	if (stopped && stop != 0) {
   4190 		/* Try again but just the visible context. */
   4191 		window_copy_visible_lines(data, &start, &end);
   4192 		stop = 0;
   4193 		goto again;
   4194 	}
   4195 
   4196 	if (!visible_only) {
   4197 		if (stopped) {
   4198 			if (nfound > 1000)
   4199 				data->searchcount = 1000;
   4200 			else if (nfound > 100)
   4201 				data->searchcount = 100;
   4202 			else if (nfound > 10)
   4203 				data->searchcount = 10;
   4204 			else
   4205 				data->searchcount = -1;
   4206 			data->searchmore = 1;
   4207 		} else {
   4208 			data->searchcount = nfound;
   4209 			data->searchmore = 0;
   4210 		}
   4211 	}
   4212 
   4213 out:
   4214 	if (ssp == &ss)
   4215 		screen_free(&ss);
   4216 	if (regex)
   4217 		regfree(&reg);
   4218 	return (1);
   4219 }
   4220 
   4221 static void
   4222 window_copy_clear_marks(struct window_mode_entry *wme)
   4223 {
   4224 	struct window_copy_mode_data	*data = wme->data;
   4225 
   4226 	free(data->searchmark);
   4227 	data->searchmark = NULL;
   4228 }
   4229 
   4230 static int
   4231 window_copy_search_up(struct window_mode_entry *wme, int regex)
   4232 {
   4233 	return (window_copy_search(wme, 0, regex));
   4234 }
   4235 
   4236 static int
   4237 window_copy_search_down(struct window_mode_entry *wme, int regex)
   4238 {
   4239 	return (window_copy_search(wme, 1, regex));
   4240 }
   4241 
   4242 static void
   4243 window_copy_goto_line(struct window_mode_entry *wme, const char *linestr)
   4244 {
   4245 	struct window_copy_mode_data	*data = wme->data;
   4246 	const char			*errstr;
   4247 	int				 lineno;
   4248 
   4249 	lineno = strtonum(linestr, -1, INT_MAX, &errstr);
   4250 	if (errstr != NULL)
   4251 		return;
   4252 	if (lineno < 0 || (u_int)lineno > screen_hsize(data->backing))
   4253 		lineno = screen_hsize(data->backing);
   4254 
   4255 	data->oy = lineno;
   4256 	window_copy_update_selection(wme, 1, 0);
   4257 	window_copy_redraw_screen(wme);
   4258 }
   4259 
   4260 static void
   4261 window_copy_match_start_end(struct window_copy_mode_data *data, u_int at,
   4262     u_int *start, u_int *end)
   4263 {
   4264 	struct grid	*gd = data->backing->grid;
   4265 	u_int		 last = (gd->sy * gd->sx) - 1;
   4266 	u_char		 mark = data->searchmark[at];
   4267 
   4268 	*start = *end = at;
   4269 	while (*start != 0 && data->searchmark[*start] == mark)
   4270 		(*start)--;
   4271 	if (data->searchmark[*start] != mark)
   4272 		(*start)++;
   4273 	while (*end != last && data->searchmark[*end] == mark)
   4274 		(*end)++;
   4275 	if (data->searchmark[*end] != mark)
   4276 		(*end)--;
   4277 }
   4278 
   4279 static char *
   4280 window_copy_match_at_cursor(struct window_copy_mode_data *data)
   4281 {
   4282 	struct grid	*gd = data->backing->grid;
   4283 	struct grid_cell gc;
   4284 	u_int		 at, start, end, cy, px, py;
   4285 	u_int		 sx = screen_size_x(data->backing);
   4286 	char		*buf = NULL;
   4287 	size_t		 len = 0;
   4288 
   4289 	if (data->searchmark == NULL)
   4290 		return (NULL);
   4291 
   4292 	cy = screen_hsize(data->backing) - data->oy + data->cy;
   4293 	if (window_copy_search_mark_at(data, data->cx, cy, &at) != 0)
   4294 		return (NULL);
   4295 	if (data->searchmark[at] == 0) {
   4296 		/* Allow one position after the match. */
   4297 		if (at == 0 || data->searchmark[--at] == 0)
   4298 			return (NULL);
   4299 	}
   4300 	window_copy_match_start_end(data, at, &start, &end);
   4301 
   4302 	/*
   4303 	 * Cells will not be set in the marked array unless they are valid text
   4304 	 * and wrapping will be taken care of, so we can just copy.
   4305  	 */
   4306 	for (at = start; at <= end; at++) {
   4307 		py = at / sx;
   4308 		px = at - (py * sx);
   4309 
   4310 		grid_get_cell(gd, px, gd->hsize + py - data->oy, &gc);
   4311 		if (gc.flags & GRID_FLAG_TAB) {
   4312 			buf = xrealloc(buf, len + 2);
   4313 			buf[len] = '\t';
   4314 			len++;
   4315 		} else if (gc.flags & GRID_FLAG_PADDING) {
   4316 			/* nothing to do */
   4317 		} else {
   4318 			buf = xrealloc(buf, len + gc.data.size + 1);
   4319 			memcpy(buf + len, gc.data.data, gc.data.size);
   4320 			len += gc.data.size;
   4321 		}
   4322 	}
   4323 	if (len != 0)
   4324 		buf[len] = '\0';
   4325 	return (buf);
   4326 }
   4327 
   4328 static void
   4329 window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
   4330     struct grid_cell *gc, const struct grid_cell *mgc,
   4331     const struct grid_cell *cgc, const struct grid_cell *mkgc)
   4332 {
   4333 	struct window_pane		*wp = wme->wp;
   4334 	struct window_copy_mode_data	*data = wme->data;
   4335 	u_int				 mark, start, end, cy, cursor, current;
   4336 	int				 inv = 0, found = 0;
   4337 	int				 keys;
   4338 
   4339 	if (data->showmark && fy == data->my) {
   4340 		gc->attr = mkgc->attr;
   4341 		if (fx == data->mx)
   4342 			inv = 1;
   4343 		if (inv) {
   4344 			gc->fg = mkgc->bg;
   4345 			gc->bg = mkgc->fg;
   4346 		}
   4347 		else {
   4348 			gc->fg = mkgc->fg;
   4349 			gc->bg = mkgc->bg;
   4350 		}
   4351 	}
   4352 
   4353 	if (data->searchmark == NULL)
   4354 		return;
   4355 
   4356 	if (window_copy_search_mark_at(data, fx, fy, &current) != 0)
   4357 		return;
   4358 	mark = data->searchmark[current];
   4359 	if (mark == 0)
   4360 		return;
   4361 
   4362 	cy = screen_hsize(data->backing) - data->oy + data->cy;
   4363 	if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) {
   4364 		keys = options_get_number(wp->window->options, "mode-keys");
   4365 		if (cursor != 0 &&
   4366 		    keys == MODEKEY_EMACS &&
   4367 		    data->searchdirection) {
   4368 			if (data->searchmark[cursor - 1] == mark) {
   4369 				cursor--;
   4370 				found = 1;
   4371 			}
   4372 		} else if (data->searchmark[cursor] == mark)
   4373 			found = 1;
   4374 		if (found) {
   4375 			window_copy_match_start_end(data, cursor, &start, &end);
   4376 			if (current >= start && current <= end) {
   4377 				gc->attr = cgc->attr;
   4378 				if (inv) {
   4379 					gc->fg = cgc->bg;
   4380 					gc->bg = cgc->fg;
   4381 				}
   4382 				else {
   4383 					gc->fg = cgc->fg;
   4384 					gc->bg = cgc->bg;
   4385 				}
   4386 				return;
   4387 			}
   4388 		}
   4389 	}
   4390 
   4391 	gc->attr = mgc->attr;
   4392 	if (inv) {
   4393 		gc->fg = mgc->bg;
   4394 		gc->bg = mgc->fg;
   4395 	}
   4396 	else {
   4397 		gc->fg = mgc->fg;
   4398 		gc->bg = mgc->bg;
   4399 	}
   4400 }
   4401 
   4402 static void
   4403 window_copy_write_one(struct window_mode_entry *wme,
   4404     struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx,
   4405     const struct grid_cell *mgc, const struct grid_cell *cgc,
   4406     const struct grid_cell *mkgc)
   4407 {
   4408 	struct window_copy_mode_data	*data = wme->data;
   4409 	struct grid			*gd = data->backing->grid;
   4410 	struct grid_cell		 gc;
   4411 	u_int		 		 fx;
   4412 
   4413 	screen_write_cursormove(ctx, 0, py, 0);
   4414 	for (fx = 0; fx < nx; fx++) {
   4415 		grid_get_cell(gd, fx, fy, &gc);
   4416 		if (fx + gc.data.width <= nx) {
   4417 			window_copy_update_style(wme, fx, fy, &gc, mgc, cgc,
   4418 			    mkgc);
   4419 			screen_write_cell(ctx, &gc);
   4420 		}
   4421 	}
   4422 }
   4423 
   4424 int
   4425 window_copy_get_current_offset(struct window_pane *wp, u_int *offset,
   4426     u_int *size)
   4427 {
   4428 	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
   4429 	struct window_copy_mode_data	*data = wme->data;
   4430 	u_int				 hsize;
   4431 
   4432 	if (data == NULL)
   4433 		return (0);
   4434 	hsize = screen_hsize(data->backing);
   4435 
   4436 	*offset = hsize - data->oy;
   4437 	*size = hsize;
   4438 	return (1);
   4439 }
   4440 
   4441 static void
   4442 window_copy_write_line(struct window_mode_entry *wme,
   4443     struct screen_write_ctx *ctx, u_int py)
   4444 {
   4445 	struct window_pane		*wp = wme->wp;
   4446 	struct window_copy_mode_data	*data = wme->data;
   4447 	struct screen			*s = &data->screen;
   4448 	struct options			*oo = wp->window->options;
   4449 	struct grid_cell		 gc, mgc, cgc, mkgc;
   4450 	u_int				 sx = screen_size_x(s);
   4451 	u_int				 hsize = screen_hsize(data->backing);
   4452 	const char			*value;
   4453 	char				*expanded;
   4454 	struct format_tree		*ft;
   4455 
   4456 	ft = format_create_defaults(NULL, NULL, NULL, NULL, wp);
   4457 
   4458 	style_apply(&gc, oo, "copy-mode-position-style", ft);
   4459 	gc.flags |= GRID_FLAG_NOPALETTE;
   4460 	style_apply(&mgc, oo, "copy-mode-match-style", ft);
   4461 	mgc.flags |= GRID_FLAG_NOPALETTE;
   4462 	style_apply(&cgc, oo, "copy-mode-current-match-style", ft);
   4463 	cgc.flags |= GRID_FLAG_NOPALETTE;
   4464 	style_apply(&mkgc, oo, "copy-mode-mark-style", ft);
   4465 	mkgc.flags |= GRID_FLAG_NOPALETTE;
   4466 
   4467 	window_copy_write_one(wme, ctx, py, hsize - data->oy + py,
   4468 	    screen_size_x(s), &mgc, &cgc, &mkgc);
   4469 
   4470 	if (py == 0 && s->rupper < s->rlower && !data->hide_position) {
   4471 		value = options_get_string(oo, "copy-mode-position-format");
   4472 		if (*value != '\0') {
   4473 			expanded = format_expand(ft, value);
   4474 			if (*expanded != '\0') {
   4475 				screen_write_cursormove(ctx, 0, 0, 0);
   4476 				format_draw(ctx, &gc, sx, expanded, NULL, 0);
   4477 			}
   4478 			free(expanded);
   4479 		}
   4480 	}
   4481 
   4482 	if (py == data->cy && data->cx == screen_size_x(s)) {
   4483 		screen_write_cursormove(ctx, screen_size_x(s) - 1, py, 0);
   4484 		screen_write_putc(ctx, &grid_default_cell, '$');
   4485 	}
   4486 
   4487 	format_free(ft);
   4488 }
   4489 
   4490 static void
   4491 window_copy_write_lines(struct window_mode_entry *wme,
   4492     struct screen_write_ctx *ctx, u_int py, u_int ny)
   4493 {
   4494 	u_int	yy;
   4495 
   4496 	for (yy = py; yy < py + ny; yy++)
   4497 		window_copy_write_line(wme, ctx, py);
   4498 }
   4499 
   4500 static void
   4501 window_copy_redraw_selection(struct window_mode_entry *wme, u_int old_y)
   4502 {
   4503 	struct window_copy_mode_data	*data = wme->data;
   4504 	struct grid			*gd = data->backing->grid;
   4505 	u_int				 new_y, start, end;
   4506 
   4507 	new_y = data->cy;
   4508 	if (old_y <= new_y) {
   4509 		start = old_y;
   4510 		end = new_y;
   4511 	} else {
   4512 		start = new_y;
   4513 		end = old_y;
   4514 	}
   4515 
   4516 	/*
   4517 	 * In word selection mode the first word on the line below the cursor
   4518 	 * might be selected, so add this line to the redraw area.
   4519 	 */
   4520 	if (data->selflag == SEL_WORD) {
   4521 		/* Last grid line in data coordinates. */
   4522 		if (end < gd->sy + data->oy - 1)
   4523 			end++;
   4524 	}
   4525 	window_copy_redraw_lines(wme, start, end - start + 1);
   4526 }
   4527 
   4528 static void
   4529 window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
   4530 {
   4531 	struct window_pane		*wp = wme->wp;
   4532 	struct window_copy_mode_data	*data = wme->data;
   4533 	struct screen_write_ctx	 	 ctx;
   4534 	u_int				 i;
   4535 
   4536 	screen_write_start_pane(&ctx, wp, NULL);
   4537 	for (i = py; i < py + ny; i++)
   4538 		window_copy_write_line(wme, &ctx, i);
   4539 	screen_write_cursormove(&ctx, data->cx, data->cy, 0);
   4540 	screen_write_stop(&ctx);
   4541 
   4542 	wp->flags |= PANE_REDRAWSCROLLBAR;
   4543 }
   4544 
   4545 static void
   4546 window_copy_redraw_screen(struct window_mode_entry *wme)
   4547 {
   4548 	struct window_copy_mode_data	*data = wme->data;
   4549 
   4550 	window_copy_redraw_lines(wme, 0, screen_size_y(&data->screen));
   4551 }
   4552 
   4553 static void
   4554 window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin,
   4555     int no_reset)
   4556 {
   4557 	struct window_copy_mode_data	*data = wme->data;
   4558 	u_int				 xx, yy;
   4559 
   4560 	xx = data->cx;
   4561 	yy = screen_hsize(data->backing) + data->cy - data->oy;
   4562 	switch (data->selflag) {
   4563 	case SEL_WORD:
   4564 		if (no_reset)
   4565 			break;
   4566 		begin = 0;
   4567 		if (data->dy > yy || (data->dy == yy && data->dx > xx)) {
   4568 			/* Right to left selection. */
   4569 			window_copy_cursor_previous_word_pos(wme,
   4570 			    data->separators, &xx, &yy);
   4571 			begin = 1;
   4572 
   4573 			/* Reset the end. */
   4574 			data->endselx = data->endselrx;
   4575 			data->endsely = data->endselry;
   4576 		} else {
   4577 			/* Left to right selection. */
   4578 			if (xx >= window_copy_find_length(wme, yy) ||
   4579 			    !window_copy_in_set(wme, xx + 1, yy, WHITESPACE)) {
   4580 				window_copy_cursor_next_word_end_pos(wme,
   4581 				    data->separators, &xx, &yy);
   4582 			}
   4583 
   4584 			/* Reset the start. */
   4585 			data->selx = data->selrx;
   4586 			data->sely = data->selry;
   4587 		}
   4588 		break;
   4589 	case SEL_LINE:
   4590 		if (no_reset)
   4591 			break;
   4592 		begin = 0;
   4593 		if (data->dy > yy) {
   4594 			/* Right to left selection. */
   4595 			xx = 0;
   4596 			begin = 1;
   4597 
   4598 			/* Reset the end. */
   4599 			data->endselx = data->endselrx;
   4600 			data->endsely = data->endselry;
   4601 		} else {
   4602 			/* Left to right selection. */
   4603 			if (yy < data->endselry)
   4604 				yy = data->endselry;
   4605 			xx = window_copy_find_length(wme, yy);
   4606 
   4607 			/* Reset the start. */
   4608 			data->selx = data->selrx;
   4609 			data->sely = data->selry;
   4610 		}
   4611 		break;
   4612 	case SEL_CHAR:
   4613 		break;
   4614 	}
   4615 	if (begin) {
   4616 		data->selx = xx;
   4617 		data->sely = yy;
   4618 	} else {
   4619 		data->endselx = xx;
   4620 		data->endsely = yy;
   4621 	}
   4622 }
   4623 
   4624 static void
   4625 window_copy_synchronize_cursor(struct window_mode_entry *wme, int no_reset)
   4626 {
   4627 	struct window_copy_mode_data	*data = wme->data;
   4628 
   4629 	switch (data->cursordrag) {
   4630 	case CURSORDRAG_ENDSEL:
   4631 		window_copy_synchronize_cursor_end(wme, 0, no_reset);
   4632 		break;
   4633 	case CURSORDRAG_SEL:
   4634 		window_copy_synchronize_cursor_end(wme, 1, no_reset);
   4635 		break;
   4636 	case CURSORDRAG_NONE:
   4637 		break;
   4638 	}
   4639 }
   4640 
   4641 static void
   4642 window_copy_update_cursor(struct window_mode_entry *wme, u_int cx, u_int cy)
   4643 {
   4644 	struct window_pane		*wp = wme->wp;
   4645 	struct window_copy_mode_data	*data = wme->data;
   4646 	struct screen			*s = &data->screen;
   4647 	struct screen_write_ctx		 ctx;
   4648 	u_int				 old_cx, old_cy;
   4649 
   4650 	old_cx = data->cx; old_cy = data->cy;
   4651 	data->cx = cx; data->cy = cy;
   4652 	if (old_cx == screen_size_x(s))
   4653 		window_copy_redraw_lines(wme, old_cy, 1);
   4654 	if (data->cx == screen_size_x(s))
   4655 		window_copy_redraw_lines(wme, data->cy, 1);
   4656 	else {
   4657 		screen_write_start_pane(&ctx, wp, NULL);
   4658 		screen_write_cursormove(&ctx, data->cx, data->cy, 0);
   4659 		screen_write_stop(&ctx);
   4660 	}
   4661 }
   4662 
   4663 static void
   4664 window_copy_start_selection(struct window_mode_entry *wme)
   4665 {
   4666 	struct window_copy_mode_data	*data = wme->data;
   4667 
   4668 	data->selx = data->cx;
   4669 	data->sely = screen_hsize(data->backing) + data->cy - data->oy;
   4670 
   4671 	data->endselx = data->selx;
   4672 	data->endsely = data->sely;
   4673 
   4674 	data->cursordrag = CURSORDRAG_ENDSEL;
   4675 
   4676 	window_copy_set_selection(wme, 1, 0);
   4677 }
   4678 
   4679 static int
   4680 window_copy_adjust_selection(struct window_mode_entry *wme, u_int *selx,
   4681     u_int *sely)
   4682 {
   4683 	struct window_copy_mode_data	*data = wme->data;
   4684 	struct screen			*s = &data->screen;
   4685 	u_int 				 sx, sy, ty;
   4686 	int				 relpos;
   4687 
   4688 	sx = *selx;
   4689 	sy = *sely;
   4690 
   4691 	ty = screen_hsize(data->backing) - data->oy;
   4692 	if (sy < ty) {
   4693 		relpos = WINDOW_COPY_REL_POS_ABOVE;
   4694 		if (!data->rectflag)
   4695 			sx = 0;
   4696 		sy = 0;
   4697 	} else if (sy > ty + screen_size_y(s) - 1) {
   4698 		relpos = WINDOW_COPY_REL_POS_BELOW;
   4699 		if (!data->rectflag)
   4700 			sx = screen_size_x(s) - 1;
   4701 		sy = screen_size_y(s) - 1;
   4702 	} else {
   4703 		relpos = WINDOW_COPY_REL_POS_ON_SCREEN;
   4704 		sy -= ty;
   4705 	}
   4706 
   4707 	*selx = sx;
   4708 	*sely = sy;
   4709 	return (relpos);
   4710 }
   4711 
   4712 static int
   4713 window_copy_update_selection(struct window_mode_entry *wme, int may_redraw,
   4714     int no_reset)
   4715 {
   4716 	struct window_copy_mode_data	*data = wme->data;
   4717 	struct screen			*s = &data->screen;
   4718 
   4719 	if (s->sel == NULL && data->lineflag == LINE_SEL_NONE)
   4720 		return (0);
   4721 	return (window_copy_set_selection(wme, may_redraw, no_reset));
   4722 }
   4723 
   4724 static int
   4725 window_copy_set_selection(struct window_mode_entry *wme, int may_redraw,
   4726     int no_reset)
   4727 {
   4728 	struct window_pane		*wp = wme->wp;
   4729 	struct window_copy_mode_data	*data = wme->data;
   4730 	struct screen			*s = &data->screen;
   4731 	struct options			*oo = wp->window->options;
   4732 	struct grid_cell		 gc;
   4733 	u_int				 sx, sy, cy, endsx, endsy;
   4734 	int				 startrelpos, endrelpos;
   4735 	struct format_tree		*ft;
   4736 
   4737 	window_copy_synchronize_cursor(wme, no_reset);
   4738 
   4739 	/* Adjust the selection. */
   4740 	sx = data->selx;
   4741 	sy = data->sely;
   4742 	startrelpos = window_copy_adjust_selection(wme, &sx, &sy);
   4743 
   4744 	/* Adjust the end of selection. */
   4745 	endsx = data->endselx;
   4746 	endsy = data->endsely;
   4747 	endrelpos = window_copy_adjust_selection(wme, &endsx, &endsy);
   4748 
   4749 	/* Selection is outside of the current screen */
   4750 	if (startrelpos == endrelpos &&
   4751 	    startrelpos != WINDOW_COPY_REL_POS_ON_SCREEN) {
   4752 		screen_hide_selection(s);
   4753 		return (0);
   4754 	}
   4755 
   4756 	/* Set colours and selection. */
   4757 	ft = format_create_defaults(NULL, NULL, NULL, NULL, wp);
   4758 	style_apply(&gc, oo, "copy-mode-selection-style", ft);
   4759 	gc.flags |= GRID_FLAG_NOPALETTE;
   4760 	format_free(ft);
   4761 	screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag,
   4762 	    data->modekeys, &gc);
   4763 
   4764 	if (data->rectflag && may_redraw) {
   4765 		/*
   4766 		 * Can't rely on the caller to redraw the right lines for
   4767 		 * rectangle selection - find the highest line and the number
   4768 		 * of lines, and redraw just past that in both directions
   4769 		 */
   4770 		cy = data->cy;
   4771 		if (data->cursordrag == CURSORDRAG_ENDSEL) {
   4772 			if (sy < cy)
   4773 				window_copy_redraw_lines(wme, sy, cy - sy + 1);
   4774 			else
   4775 				window_copy_redraw_lines(wme, cy, sy - cy + 1);
   4776 		} else {
   4777 			if (endsy < cy) {
   4778 				window_copy_redraw_lines(wme, endsy,
   4779 				    cy - endsy + 1);
   4780 			} else {
   4781 				window_copy_redraw_lines(wme, cy,
   4782 				    endsy - cy + 1);
   4783 			}
   4784 		}
   4785 	}
   4786 
   4787 	return (1);
   4788 }
   4789 
   4790 static void *
   4791 window_copy_get_selection(struct window_mode_entry *wme, size_t *len)
   4792 {
   4793 	struct window_pane		*wp = wme->wp;
   4794 	struct window_copy_mode_data	*data = wme->data;
   4795 	struct screen			*s = &data->screen;
   4796 	char				*buf;
   4797 	size_t				 off;
   4798 	u_int				 i, xx, yy, sx, sy, ex, ey, ey_last;
   4799 	u_int				 firstsx, lastex, restex, restsx, selx;
   4800 	int				 keys;
   4801 
   4802 	if (data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE) {
   4803 		buf = window_copy_match_at_cursor(data);
   4804 		if (buf != NULL)
   4805 			*len = strlen(buf);
   4806 		else
   4807 			*len = 0;
   4808 		return (buf);
   4809 	}
   4810 
   4811 	buf = xmalloc(1);
   4812 	off = 0;
   4813 
   4814 	*buf = '\0';
   4815 
   4816 	/*
   4817 	 * The selection extends from selx,sely to (adjusted) cx,cy on
   4818 	 * the base screen.
   4819 	 */
   4820 
   4821 	/* Find start and end. */
   4822 	xx = data->endselx;
   4823 	yy = data->endsely;
   4824 	if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
   4825 		sx = xx; sy = yy;
   4826 		ex = data->selx; ey = data->sely;
   4827 	} else {
   4828 		sx = data->selx; sy = data->sely;
   4829 		ex = xx; ey = yy;
   4830 	}
   4831 
   4832 	/* Trim ex to end of line. */
   4833 	ey_last = window_copy_find_length(wme, ey);
   4834 	if (ex > ey_last)
   4835 		ex = ey_last;
   4836 
   4837 	/*
   4838 	 * Deal with rectangle-copy if necessary; four situations: start of
   4839 	 * first line (firstsx), end of last line (lastex), start (restsx) and
   4840 	 * end (restex) of all other lines.
   4841 	 */
   4842 	xx = screen_size_x(s);
   4843 
   4844 	/*
   4845 	 * Behave according to mode-keys. If it is emacs, copy like emacs,
   4846 	 * keeping the top-left-most character, and dropping the
   4847 	 * bottom-right-most, regardless of copy direction. If it is vi, also
   4848 	 * keep bottom-right-most character.
   4849 	 */
   4850 	keys = options_get_number(wp->window->options, "mode-keys");
   4851 	if (data->rectflag) {
   4852 		/*
   4853 		 * Need to ignore the column with the cursor in it, which for
   4854 		 * rectangular copy means knowing which side the cursor is on.
   4855 		 */
   4856 		if (data->cursordrag == CURSORDRAG_ENDSEL)
   4857 			selx = data->selx;
   4858 		else
   4859 			selx = data->endselx;
   4860 		if (selx < data->cx) {
   4861 			/* Selection start is on the left. */
   4862 			if (keys == MODEKEY_EMACS) {
   4863 				lastex = data->cx;
   4864 				restex = data->cx;
   4865 			}
   4866 			else {
   4867 				lastex = data->cx + 1;
   4868 				restex = data->cx + 1;
   4869 			}
   4870 			firstsx = selx;
   4871 			restsx = selx;
   4872 		} else {
   4873 			/* Cursor is on the left. */
   4874 			lastex = selx + 1;
   4875 			restex = selx + 1;
   4876 			firstsx = data->cx;
   4877 			restsx = data->cx;
   4878 		}
   4879 	} else {
   4880 		if (keys == MODEKEY_EMACS)
   4881 			lastex = ex;
   4882 		else
   4883 			lastex = ex + 1;
   4884 		restex = xx;
   4885 		firstsx = sx;
   4886 		restsx = 0;
   4887 	}
   4888 
   4889 	/* Copy the lines. */
   4890 	for (i = sy; i <= ey; i++) {
   4891 		window_copy_copy_line(wme, &buf, &off, i,
   4892 		    (i == sy ? firstsx : restsx),
   4893 		    (i == ey ? lastex : restex));
   4894 	}
   4895 
   4896 	/* Don't bother if no data. */
   4897 	if (off == 0) {
   4898 		free(buf);
   4899 		*len = 0;
   4900 		return (NULL);
   4901 	}
   4902 	 /* Remove final \n (unless at end in vi mode). */
   4903 	if (keys == MODEKEY_EMACS || lastex <= ey_last) {
   4904 		if (~grid_get_line(data->backing->grid, ey)->flags &
   4905 		    GRID_LINE_WRAPPED || lastex != ey_last)
   4906 			off -= 1;
   4907 	}
   4908 	*len = off;
   4909 	return (buf);
   4910 }
   4911 
   4912 static void
   4913 window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix,
   4914     void *buf, size_t len, int set_paste, int set_clip)
   4915 {
   4916 	struct window_pane	*wp = wme->wp;
   4917 	struct screen_write_ctx	 ctx;
   4918 
   4919 	if (set_clip &&
   4920 	    options_get_number(global_options, "set-clipboard") != 0) {
   4921 		screen_write_start_pane(&ctx, wp, NULL);
   4922 		screen_write_setselection(&ctx, "", buf, len);
   4923 		screen_write_stop(&ctx);
   4924 		notify_pane("pane-set-clipboard", wp);
   4925 	}
   4926 
   4927 	if (set_paste)
   4928 		paste_add(prefix, buf, len);
   4929 	else
   4930 		free(buf);
   4931 }
   4932 
   4933 static void *
   4934 window_copy_pipe_run(struct window_mode_entry *wme, struct session *s,
   4935     const char *cmd, size_t *len)
   4936 {
   4937 	void		*buf;
   4938 	struct job	*job;
   4939 
   4940 	buf = window_copy_get_selection(wme, len);
   4941 	if (cmd == NULL || *cmd == '\0')
   4942 		cmd = options_get_string(global_options, "copy-command");
   4943 	if (cmd != NULL && *cmd != '\0') {
   4944 		job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL,
   4945 		    NULL, JOB_NOWAIT, -1, -1);
   4946 		bufferevent_write(job_get_event(job), buf, *len);
   4947 	}
   4948 	return (buf);
   4949 }
   4950 
   4951 static void
   4952 window_copy_pipe(struct window_mode_entry *wme, struct session *s,
   4953     const char *cmd)
   4954 {
   4955 	void	*buf;
   4956 	size_t	len;
   4957 
   4958 	buf = window_copy_pipe_run(wme, s, cmd, &len);
   4959 	free (buf);
   4960 }
   4961 
   4962 static void
   4963 window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s,
   4964     const char *prefix, const char *cmd, int set_paste, int set_clip)
   4965 {
   4966 	void	*buf;
   4967 	size_t	 len;
   4968 
   4969 	buf = window_copy_pipe_run(wme, s, cmd, &len);
   4970 	if (buf != NULL) {
   4971 		window_copy_copy_buffer(wme, prefix, buf, len, set_paste,
   4972 		    set_clip);
   4973 	}
   4974 }
   4975 
   4976 static void
   4977 window_copy_copy_selection(struct window_mode_entry *wme, const char *prefix,
   4978     int set_paste, int set_clip)
   4979 {
   4980 	char	*buf;
   4981 	size_t	 len;
   4982 
   4983 	buf = window_copy_get_selection(wme, &len);
   4984 	if (buf != NULL) {
   4985 		window_copy_copy_buffer(wme, prefix, buf, len, set_paste,
   4986 		    set_clip);
   4987 	}
   4988 }
   4989 
   4990 static void
   4991 window_copy_append_selection(struct window_mode_entry *wme)
   4992 {
   4993 	struct window_pane		*wp = wme->wp;
   4994 	char				*buf;
   4995 	struct paste_buffer		*pb;
   4996 	const char			*bufdata, *bufname = NULL;
   4997 	size_t				 len, bufsize;
   4998 	struct screen_write_ctx		 ctx;
   4999 
   5000 	buf = window_copy_get_selection(wme, &len);
   5001 	if (buf == NULL)
   5002 		return;
   5003 
   5004 	if (options_get_number(global_options, "set-clipboard") != 0) {
   5005 		screen_write_start_pane(&ctx, wp, NULL);
   5006 		screen_write_setselection(&ctx, "", (u_char *)buf, len);
   5007 		screen_write_stop(&ctx);
   5008 		notify_pane("pane-set-clipboard", wp);
   5009 	}
   5010 
   5011 	pb = paste_get_top(&bufname);
   5012 	if (pb != NULL) {
   5013 		bufdata = paste_buffer_data(pb, &bufsize);
   5014 		buf = xrealloc(buf, len + bufsize);
   5015 		memmove(buf + bufsize, buf, len);
   5016 		memcpy(buf, bufdata, bufsize);
   5017 		len += bufsize;
   5018 	}
   5019 	if (paste_set(buf, len, bufname, NULL) != 0)
   5020 		free(buf);
   5021 }
   5022 
   5023 static void
   5024 window_copy_copy_line(struct window_mode_entry *wme, char **buf, size_t *off,
   5025     u_int sy, u_int sx, u_int ex)
   5026 {
   5027 	struct window_copy_mode_data	*data = wme->data;
   5028 	struct grid			*gd = data->backing->grid;
   5029 	struct grid_cell		 gc;
   5030 	struct grid_line		*gl;
   5031 	struct utf8_data		 ud;
   5032 	u_int				 i, xx, wrapped = 0;
   5033 	const char			*s;
   5034 
   5035 	if (sx > ex)
   5036 		return;
   5037 
   5038 	/*
   5039 	 * Work out if the line was wrapped at the screen edge and all of it is
   5040 	 * on screen.
   5041 	 */
   5042 	gl = grid_get_line(gd, sy);
   5043 	if (gl->flags & GRID_LINE_WRAPPED && gl->cellsize <= gd->sx)
   5044 		wrapped = 1;
   5045 
   5046 	/* If the line was wrapped, don't strip spaces (use the full length). */
   5047 	if (wrapped)
   5048 		xx = gl->cellsize;
   5049 	else
   5050 		xx = window_copy_find_length(wme, sy);
   5051 	if (ex > xx)
   5052 		ex = xx;
   5053 	if (sx > xx)
   5054 		sx = xx;
   5055 
   5056 	if (sx < ex) {
   5057 		for (i = sx; i < ex; i++) {
   5058 			grid_get_cell(gd, i, sy, &gc);
   5059 			if (gc.flags & GRID_FLAG_PADDING)
   5060 				continue;
   5061 			if (gc.flags & GRID_FLAG_TAB)
   5062 				utf8_set(&ud, '\t');
   5063 			else
   5064 				utf8_copy(&ud, &gc.data);
   5065 			if (ud.size == 1 && (gc.attr & GRID_ATTR_CHARSET)) {
   5066 				s = tty_acs_get(NULL, ud.data[0]);
   5067 				if (s != NULL && strlen(s) <= sizeof ud.data) {
   5068 					ud.size = strlen(s);
   5069 					memcpy(ud.data, s, ud.size);
   5070 				}
   5071 			}
   5072 
   5073 			*buf = xrealloc(*buf, (*off) + ud.size);
   5074 			memcpy(*buf + *off, ud.data, ud.size);
   5075 			*off += ud.size;
   5076 		}
   5077 	}
   5078 
   5079 	/* Only add a newline if the line wasn't wrapped. */
   5080 	if (!wrapped || ex != xx) {
   5081 		*buf = xrealloc(*buf, (*off) + 1);
   5082 		(*buf)[(*off)++] = '\n';
   5083 	}
   5084 }
   5085 
   5086 static void
   5087 window_copy_clear_selection(struct window_mode_entry *wme)
   5088 {
   5089 	struct window_copy_mode_data   *data = wme->data;
   5090 	u_int				px, py;
   5091 
   5092 	screen_clear_selection(&data->screen);
   5093 
   5094 	data->cursordrag = CURSORDRAG_NONE;
   5095 	data->lineflag = LINE_SEL_NONE;
   5096 	data->selflag = SEL_CHAR;
   5097 
   5098 	py = screen_hsize(data->backing) + data->cy - data->oy;
   5099 	px = window_copy_find_length(wme, py);
   5100 	if (data->cx > px)
   5101 		window_copy_update_cursor(wme, px, data->cy);
   5102 }
   5103 
   5104 static int
   5105 window_copy_in_set(struct window_mode_entry *wme, u_int px, u_int py,
   5106     const char *set)
   5107 {
   5108 	struct window_copy_mode_data	*data = wme->data;
   5109 
   5110 	return (grid_in_set(data->backing->grid, px, py, set));
   5111 }
   5112 
   5113 static u_int
   5114 window_copy_find_length(struct window_mode_entry *wme, u_int py)
   5115 {
   5116 	struct window_copy_mode_data	*data = wme->data;
   5117 
   5118 	return (grid_line_length(data->backing->grid, py));
   5119 }
   5120 
   5121 static void
   5122 window_copy_cursor_start_of_line(struct window_mode_entry *wme)
   5123 {
   5124 	struct window_copy_mode_data	*data = wme->data;
   5125 	struct screen			*back_s = data->backing;
   5126 	struct grid_reader		 gr;
   5127 	u_int				 px, py, oldy, hsize;
   5128 
   5129 	px = data->cx;
   5130 	hsize = screen_hsize(back_s);
   5131 	py = hsize + data->cy - data->oy;
   5132 	oldy = data->cy;
   5133 
   5134 	grid_reader_start(&gr, back_s->grid, px, py);
   5135 	grid_reader_cursor_start_of_line(&gr, 1);
   5136 	grid_reader_get_cursor(&gr, &px, &py);
   5137 	window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
   5138 }
   5139 
   5140 static void
   5141 window_copy_cursor_back_to_indentation(struct window_mode_entry *wme)
   5142 {
   5143 	struct window_copy_mode_data	*data = wme->data;
   5144 	struct screen			*back_s = data->backing;
   5145 	struct grid_reader		 gr;
   5146 	u_int				 px, py, oldy, hsize;
   5147 
   5148 	px = data->cx;
   5149 	hsize = screen_hsize(back_s);
   5150 	py = hsize + data->cy - data->oy;
   5151 	oldy = data->cy;
   5152 
   5153 	grid_reader_start(&gr, back_s->grid, px, py);
   5154 	grid_reader_cursor_back_to_indentation(&gr);
   5155 	grid_reader_get_cursor(&gr, &px, &py);
   5156 	window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
   5157 }
   5158 
   5159 static void
   5160 window_copy_cursor_end_of_line(struct window_mode_entry *wme)
   5161 {
   5162 	struct window_copy_mode_data	*data = wme->data;
   5163 	struct screen			*back_s = data->backing;
   5164 	struct grid_reader		 gr;
   5165 	u_int				 px, py, oldy, hsize;
   5166 
   5167 	px = data->cx;
   5168 	hsize = screen_hsize(back_s);
   5169 	py =  hsize + data->cy - data->oy;
   5170 	oldy = data->cy;
   5171 
   5172 	grid_reader_start(&gr, back_s->grid, px, py);
   5173 	if (data->screen.sel != NULL && data->rectflag)
   5174 		grid_reader_cursor_end_of_line(&gr, 1, 1);
   5175 	else
   5176 		grid_reader_cursor_end_of_line(&gr, 1, 0);
   5177 	grid_reader_get_cursor(&gr, &px, &py);
   5178 	window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
   5179 	    data->oy, oldy, px, py, 0);
   5180 }
   5181 
   5182 static void
   5183 window_copy_other_end(struct window_mode_entry *wme)
   5184 {
   5185 	struct window_copy_mode_data	*data = wme->data;
   5186 	struct screen			*s = &data->screen;
   5187 	u_int				 selx, sely, cy, yy, hsize;
   5188 
   5189 	if (s->sel == NULL && data->lineflag == LINE_SEL_NONE)
   5190 		return;
   5191 
   5192 	if (data->lineflag == LINE_SEL_LEFT_RIGHT)
   5193 		data->lineflag = LINE_SEL_RIGHT_LEFT;
   5194 	else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
   5195 		data->lineflag = LINE_SEL_LEFT_RIGHT;
   5196 
   5197 	switch (data->cursordrag) {
   5198 		case CURSORDRAG_NONE:
   5199 		case CURSORDRAG_SEL:
   5200 			data->cursordrag = CURSORDRAG_ENDSEL;
   5201 			break;
   5202 		case CURSORDRAG_ENDSEL:
   5203 			data->cursordrag = CURSORDRAG_SEL;
   5204 			break;
   5205 	}
   5206 
   5207 	selx = data->endselx;
   5208 	sely = data->endsely;
   5209 	if (data->cursordrag == CURSORDRAG_SEL) {
   5210 		selx = data->selx;
   5211 		sely = data->sely;
   5212 	}
   5213 
   5214 	cy = data->cy;
   5215 	yy = screen_hsize(data->backing) + data->cy - data->oy;
   5216 
   5217 	data->cx = selx;
   5218 
   5219 	hsize = screen_hsize(data->backing);
   5220 	if (sely < hsize - data->oy) { /* above */
   5221 		data->oy = hsize - sely;
   5222 		data->cy = 0;
   5223 	} else if (sely > hsize - data->oy + screen_size_y(s)) { /* below */
   5224 		data->oy = hsize - sely + screen_size_y(s) - 1;
   5225 		data->cy = screen_size_y(s) - 1;
   5226 	} else
   5227 		data->cy = cy + sely - yy;
   5228 
   5229 	window_copy_update_selection(wme, 1, 1);
   5230 	window_copy_redraw_screen(wme);
   5231 }
   5232 
   5233 static void
   5234 window_copy_cursor_left(struct window_mode_entry *wme)
   5235 {
   5236 	struct window_copy_mode_data	*data = wme->data;
   5237 	struct screen			*back_s = data->backing;
   5238 	struct grid_reader		 gr;
   5239 	u_int				 px, py, oldy, hsize;
   5240 
   5241 	px = data->cx;
   5242 	hsize = screen_hsize(back_s);
   5243 	py = hsize + data->cy - data->oy;
   5244 	oldy = data->cy;
   5245 
   5246 	grid_reader_start(&gr, back_s->grid, px, py);
   5247 	grid_reader_cursor_left(&gr, 1);
   5248 	grid_reader_get_cursor(&gr, &px, &py);
   5249 	window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
   5250 }
   5251 
   5252 static void
   5253 window_copy_cursor_right(struct window_mode_entry *wme, int all)
   5254 {
   5255 	struct window_copy_mode_data	*data = wme->data;
   5256 	struct screen			*back_s = data->backing;
   5257 	struct grid_reader		 gr;
   5258 	u_int				 px, py, oldy, hsize;
   5259 
   5260 	px = data->cx;
   5261 	hsize = screen_hsize(back_s);
   5262 	py = hsize + data->cy - data->oy;
   5263 	oldy = data->cy;
   5264 
   5265 	grid_reader_start(&gr, back_s->grid, px, py);
   5266 	grid_reader_cursor_right(&gr, 1, all);
   5267 	grid_reader_get_cursor(&gr, &px, &py);
   5268 	window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
   5269 	    data->oy, oldy, px, py, 0);
   5270 }
   5271 
   5272 static void
   5273 window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
   5274 {
   5275 	struct window_copy_mode_data	*data = wme->data;
   5276 	struct screen			*s = &data->screen;
   5277 	u_int				 ox, oy, px, py;
   5278 	int				 norectsel;
   5279 
   5280 	norectsel = data->screen.sel == NULL || !data->rectflag;
   5281 	oy = screen_hsize(data->backing) + data->cy - data->oy;
   5282 	ox = window_copy_find_length(wme, oy);
   5283 	if (norectsel && data->cx != ox) {
   5284 		data->lastcx = data->cx;
   5285 		data->lastsx = ox;
   5286 	}
   5287 
   5288 	if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
   5289 		window_copy_other_end(wme);
   5290 
   5291 	if (scroll_only || data->cy == 0) {
   5292 		if (norectsel)
   5293 			data->cx = data->lastcx;
   5294 		window_copy_scroll_down(wme, 1);
   5295 		if (scroll_only) {
   5296 			if (data->cy == screen_size_y(s) - 1)
   5297 				window_copy_redraw_lines(wme, data->cy, 1);
   5298 			else
   5299 				window_copy_redraw_lines(wme, data->cy, 2);
   5300 		}
   5301 	} else {
   5302 		if (norectsel) {
   5303 			window_copy_update_cursor(wme, data->lastcx,
   5304 			    data->cy - 1);
   5305 		} else
   5306 			window_copy_update_cursor(wme, data->cx, data->cy - 1);
   5307 		if (window_copy_update_selection(wme, 1, 0)) {
   5308 			if (data->cy == screen_size_y(s) - 1)
   5309 				window_copy_redraw_lines(wme, data->cy, 1);
   5310 			else
   5311 				window_copy_redraw_lines(wme, data->cy, 2);
   5312 		}
   5313 	}
   5314 
   5315 	if (norectsel) {
   5316 		py = screen_hsize(data->backing) + data->cy - data->oy;
   5317 		px = window_copy_find_length(wme, py);
   5318 		if ((data->cx >= data->lastsx && data->cx != px) ||
   5319 		    data->cx > px)
   5320 		{
   5321 			window_copy_update_cursor(wme, px, data->cy);
   5322 			if (window_copy_update_selection(wme, 1, 0))
   5323 				window_copy_redraw_lines(wme, data->cy, 1);
   5324 		}
   5325 	}
   5326 
   5327 	if (data->lineflag == LINE_SEL_LEFT_RIGHT)
   5328 	{
   5329 		py = screen_hsize(data->backing) + data->cy - data->oy;
   5330 		if (data->rectflag)
   5331 			px = screen_size_x(data->backing);
   5332 		else
   5333 			px = window_copy_find_length(wme, py);
   5334 		window_copy_update_cursor(wme, px, data->cy);
   5335 		if (window_copy_update_selection(wme, 1, 0))
   5336 			window_copy_redraw_lines(wme, data->cy, 1);
   5337 	}
   5338 	else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
   5339 	{
   5340 		window_copy_update_cursor(wme, 0, data->cy);
   5341 		if (window_copy_update_selection(wme, 1, 0))
   5342 			window_copy_redraw_lines(wme, data->cy, 1);
   5343 	}
   5344 }
   5345 
   5346 static void
   5347 window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
   5348 {
   5349 	struct window_copy_mode_data	*data = wme->data;
   5350 	struct screen			*s = &data->screen;
   5351 	u_int				 ox, oy, px, py;
   5352 	int				 norectsel;
   5353 
   5354 	norectsel = data->screen.sel == NULL || !data->rectflag;
   5355 	oy = screen_hsize(data->backing) + data->cy - data->oy;
   5356 	ox = window_copy_find_length(wme, oy);
   5357 	if (norectsel && data->cx != ox) {
   5358 		data->lastcx = data->cx;
   5359 		data->lastsx = ox;
   5360 	}
   5361 
   5362 	if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
   5363 		window_copy_other_end(wme);
   5364 
   5365 	if (scroll_only || data->cy == screen_size_y(s) - 1) {
   5366 		if (norectsel)
   5367 			data->cx = data->lastcx;
   5368 		window_copy_scroll_up(wme, 1);
   5369 		if (scroll_only && data->cy > 0)
   5370 			window_copy_redraw_lines(wme, data->cy - 1, 2);
   5371 	} else {
   5372 		if (norectsel) {
   5373 			window_copy_update_cursor(wme, data->lastcx,
   5374 			    data->cy + 1);
   5375 		} else
   5376 			window_copy_update_cursor(wme, data->cx, data->cy + 1);
   5377 		if (window_copy_update_selection(wme, 1, 0))
   5378 			window_copy_redraw_lines(wme, data->cy - 1, 2);
   5379 	}
   5380 
   5381 	if (norectsel) {
   5382 		py = screen_hsize(data->backing) + data->cy - data->oy;
   5383 		px = window_copy_find_length(wme, py);
   5384 		if ((data->cx >= data->lastsx && data->cx != px) ||
   5385 		    data->cx > px)
   5386 		{
   5387 			window_copy_update_cursor(wme, px, data->cy);
   5388 			if (window_copy_update_selection(wme, 1, 0))
   5389 				window_copy_redraw_lines(wme, data->cy, 1);
   5390 		}
   5391 	}
   5392 
   5393 	if (data->lineflag == LINE_SEL_LEFT_RIGHT)
   5394 	{
   5395 		py = screen_hsize(data->backing) + data->cy - data->oy;
   5396 		if (data->rectflag)
   5397 			px = screen_size_x(data->backing);
   5398 		else
   5399 			px = window_copy_find_length(wme, py);
   5400 		window_copy_update_cursor(wme, px, data->cy);
   5401 		if (window_copy_update_selection(wme, 1, 0))
   5402 			window_copy_redraw_lines(wme, data->cy, 1);
   5403 	}
   5404 	else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
   5405 	{
   5406 		window_copy_update_cursor(wme, 0, data->cy);
   5407 		if (window_copy_update_selection(wme, 1, 0))
   5408 			window_copy_redraw_lines(wme, data->cy, 1);
   5409 	}
   5410 }
   5411 
   5412 static void
   5413 window_copy_cursor_jump(struct window_mode_entry *wme)
   5414 {
   5415 	struct window_copy_mode_data	*data = wme->data;
   5416 	struct screen			*back_s = data->backing;
   5417 	struct grid_reader		 gr;
   5418 	u_int				 px, py, oldy, hsize;
   5419 
   5420 	px = data->cx + 1;
   5421 	hsize = screen_hsize(back_s);
   5422 	py = hsize + data->cy - data->oy;
   5423 	oldy = data->cy;
   5424 
   5425 	grid_reader_start(&gr, back_s->grid, px, py);
   5426 	if (grid_reader_cursor_jump(&gr, data->jumpchar)) {
   5427 		grid_reader_get_cursor(&gr, &px, &py);
   5428 		window_copy_acquire_cursor_down(wme, hsize,
   5429 		    screen_size_y(back_s), data->oy, oldy, px, py, 0);
   5430 	}
   5431 }
   5432 
   5433 static void
   5434 window_copy_cursor_jump_back(struct window_mode_entry *wme)
   5435 {
   5436 	struct window_copy_mode_data	*data = wme->data;
   5437 	struct screen			*back_s = data->backing;
   5438 	struct grid_reader		 gr;
   5439 	u_int				 px, py, oldy, hsize;
   5440 
   5441 	px = data->cx;
   5442 	hsize = screen_hsize(back_s);
   5443 	py = hsize + data->cy - data->oy;
   5444 	oldy = data->cy;
   5445 
   5446 	grid_reader_start(&gr, back_s->grid, px, py);
   5447 	grid_reader_cursor_left(&gr, 0);
   5448 	if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
   5449 		grid_reader_get_cursor(&gr, &px, &py);
   5450 		window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px,
   5451 		    py);
   5452 	}
   5453 }
   5454 
   5455 static void
   5456 window_copy_cursor_jump_to(struct window_mode_entry *wme)
   5457 {
   5458 	struct window_copy_mode_data	*data = wme->data;
   5459 	struct screen			*back_s = data->backing;
   5460 	struct grid_reader		 gr;
   5461 	u_int				 px, py, oldy, hsize;
   5462 
   5463 	px = data->cx + 2;
   5464 	hsize = screen_hsize(back_s);
   5465 	py = hsize + data->cy - data->oy;
   5466 	oldy = data->cy;
   5467 
   5468 	grid_reader_start(&gr, back_s->grid, px, py);
   5469 	if (grid_reader_cursor_jump(&gr, data->jumpchar)) {
   5470 		grid_reader_cursor_left(&gr, 1);
   5471 		grid_reader_get_cursor(&gr, &px, &py);
   5472 		window_copy_acquire_cursor_down(wme, hsize,
   5473 		    screen_size_y(back_s), data->oy, oldy, px, py, 0);
   5474 	}
   5475 }
   5476 
   5477 static void
   5478 window_copy_cursor_jump_to_back(struct window_mode_entry *wme)
   5479 {
   5480 	struct window_copy_mode_data	*data = wme->data;
   5481 	struct screen			*back_s = data->backing;
   5482 	struct grid_reader		 gr;
   5483 	u_int				 px, py, oldy, hsize;
   5484 
   5485 	px = data->cx;
   5486 	hsize = screen_hsize(back_s);
   5487 	py = hsize + data->cy - data->oy;
   5488 	oldy = data->cy;
   5489 
   5490 	grid_reader_start(&gr, back_s->grid, px, py);
   5491 	grid_reader_cursor_left(&gr, 0);
   5492 	grid_reader_cursor_left(&gr, 0);
   5493 	if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) {
   5494 		grid_reader_cursor_right(&gr, 1, 0);
   5495 		grid_reader_get_cursor(&gr, &px, &py);
   5496 		window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px,
   5497 		    py);
   5498 	}
   5499 }
   5500 
   5501 static void
   5502 window_copy_cursor_next_word(struct window_mode_entry *wme,
   5503     const char *separators)
   5504 {
   5505 	struct window_copy_mode_data	*data = wme->data;
   5506 	struct screen			*back_s = data->backing;
   5507 	struct grid_reader		 gr;
   5508 	u_int				 px, py, oldy, hsize;
   5509 
   5510 	px = data->cx;
   5511 	hsize = screen_hsize(back_s);
   5512 	py =  hsize + data->cy - data->oy;
   5513 	oldy = data->cy;
   5514 
   5515 	grid_reader_start(&gr, back_s->grid, px, py);
   5516 	grid_reader_cursor_next_word(&gr, separators);
   5517 	grid_reader_get_cursor(&gr, &px, &py);
   5518 	window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
   5519 	    data->oy, oldy, px, py, 0);
   5520 }
   5521 
   5522 /* Compute the next place where a word ends. */
   5523 static void
   5524 window_copy_cursor_next_word_end_pos(struct window_mode_entry *wme,
   5525     const char *separators, u_int *ppx, u_int *ppy)
   5526 {
   5527 	struct window_pane		*wp = wme->wp;
   5528 	struct window_copy_mode_data	*data = wme->data;
   5529 	struct options			*oo = wp->window->options;
   5530 	struct screen			*back_s = data->backing;
   5531 	struct grid_reader		 gr;
   5532 	u_int				 px, py, hsize;
   5533 
   5534 	px = data->cx;
   5535 	hsize = screen_hsize(back_s);
   5536 	py =  hsize + data->cy - data->oy;
   5537 
   5538 	grid_reader_start(&gr, back_s->grid, px, py);
   5539 	if (options_get_number(oo, "mode-keys") == MODEKEY_VI) {
   5540 		if (!grid_reader_in_set(&gr, WHITESPACE))
   5541 			grid_reader_cursor_right(&gr, 0, 0);
   5542 		grid_reader_cursor_next_word_end(&gr, separators);
   5543 		grid_reader_cursor_left(&gr, 1);
   5544 	} else
   5545 		grid_reader_cursor_next_word_end(&gr, separators);
   5546 	grid_reader_get_cursor(&gr, &px, &py);
   5547 	*ppx = px;
   5548 	*ppy = py;
   5549 }
   5550 
   5551 /* Move to the next place where a word ends. */
   5552 static void
   5553 window_copy_cursor_next_word_end(struct window_mode_entry *wme,
   5554     const char *separators, int no_reset)
   5555 {
   5556 	struct window_pane		*wp = wme->wp;
   5557 	struct window_copy_mode_data	*data = wme->data;
   5558 	struct options			*oo = wp->window->options;
   5559 	struct screen			*back_s = data->backing;
   5560 	struct grid_reader		 gr;
   5561 	u_int				 px, py, oldy, hsize;
   5562 
   5563 	px = data->cx;
   5564 	hsize = screen_hsize(back_s);
   5565 	py =  hsize + data->cy - data->oy;
   5566 	oldy = data->cy;
   5567 
   5568 	grid_reader_start(&gr, back_s->grid, px, py);
   5569 	if (options_get_number(oo, "mode-keys") == MODEKEY_VI) {
   5570 		if (!grid_reader_in_set(&gr, WHITESPACE))
   5571 			grid_reader_cursor_right(&gr, 0, 0);
   5572 		grid_reader_cursor_next_word_end(&gr, separators);
   5573 		grid_reader_cursor_left(&gr, 1);
   5574 	} else
   5575 		grid_reader_cursor_next_word_end(&gr, separators);
   5576 	grid_reader_get_cursor(&gr, &px, &py);
   5577 	window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s),
   5578 	    data->oy, oldy, px, py, no_reset);
   5579 }
   5580 
   5581 /* Compute the previous place where a word begins. */
   5582 static void
   5583 window_copy_cursor_previous_word_pos(struct window_mode_entry *wme,
   5584     const char *separators, u_int *ppx, u_int *ppy)
   5585 {
   5586 	struct window_copy_mode_data	*data = wme->data;
   5587 	struct screen			*back_s = data->backing;
   5588 	struct grid_reader		 gr;
   5589 	u_int				 px, py, hsize;
   5590 
   5591 	px = data->cx;
   5592 	hsize = screen_hsize(back_s);
   5593 	py = hsize + data->cy - data->oy;
   5594 
   5595 	grid_reader_start(&gr, back_s->grid, px, py);
   5596 	grid_reader_cursor_previous_word(&gr, separators, 0, 1);
   5597 	grid_reader_get_cursor(&gr, &px, &py);
   5598 	*ppx = px;
   5599 	*ppy = py;
   5600 }
   5601 
   5602 /* Move to the previous place where a word begins. */
   5603 static void
   5604 window_copy_cursor_previous_word(struct window_mode_entry *wme,
   5605     const char *separators, int already)
   5606 {
   5607 	struct window_copy_mode_data	*data = wme->data;
   5608 	struct window			*w = wme->wp->window;
   5609 	struct screen			*back_s = data->backing;
   5610 	struct grid_reader		 gr;
   5611 	u_int				 px, py, oldy, hsize;
   5612 	int				 stop_at_eol;
   5613 
   5614 	if (options_get_number(w->options, "mode-keys") == MODEKEY_EMACS)
   5615 		stop_at_eol = 1;
   5616 	else
   5617 		stop_at_eol = 0;
   5618 
   5619 	px = data->cx;
   5620 	hsize = screen_hsize(back_s);
   5621 	py = hsize + data->cy - data->oy;
   5622 	oldy = data->cy;
   5623 
   5624 	grid_reader_start(&gr, back_s->grid, px, py);
   5625 	grid_reader_cursor_previous_word(&gr, separators, already, stop_at_eol);
   5626 	grid_reader_get_cursor(&gr, &px, &py);
   5627 	window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py);
   5628 }
   5629 
   5630 static void
   5631 window_copy_cursor_prompt(struct window_mode_entry *wme, int direction,
   5632     int start_output)
   5633 {
   5634 	struct window_copy_mode_data	*data = wme->data;
   5635 	struct screen			*s = data->backing;
   5636 	struct grid			*gd = s->grid;
   5637 	u_int				 end_line;
   5638 	u_int				 line = gd->hsize - data->oy + data->cy;
   5639 	int				 add, line_flag;
   5640 
   5641 	if (start_output)
   5642 		line_flag = GRID_LINE_START_OUTPUT;
   5643 	else
   5644 		line_flag = GRID_LINE_START_PROMPT;
   5645 
   5646 	if (direction == 0) { /* up */
   5647 		add = -1;
   5648 		end_line = 0;
   5649 	} else { /* down */
   5650 		add = 1;
   5651 		end_line = gd->hsize + gd->sy - 1;
   5652 	}
   5653 
   5654 	if (line == end_line)
   5655 		return;
   5656 	for (;;) {
   5657 		if (line == end_line)
   5658 			return;
   5659 		line += add;
   5660 
   5661 		if (grid_get_line(gd, line)->flags & line_flag)
   5662 			break;
   5663 	}
   5664 
   5665 	data->cx = 0;
   5666 	if (line > gd->hsize) {
   5667 		data->cy = line - gd->hsize;
   5668 		data->oy = 0;
   5669 	} else {
   5670 		data->cy = 0;
   5671 		data->oy = gd->hsize - line;
   5672 	}
   5673 
   5674 	window_copy_update_selection(wme, 1, 0);
   5675 	window_copy_redraw_screen(wme);
   5676 }
   5677 
   5678 static void
   5679 window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
   5680 {
   5681 	struct window_pane		*wp = wme->wp;
   5682 	struct window_copy_mode_data	*data = wme->data;
   5683 	struct screen			*s = &data->screen;
   5684 	struct screen_write_ctx		 ctx;
   5685 
   5686 	if (data->oy < ny)
   5687 		ny = data->oy;
   5688 	if (ny == 0)
   5689 		return;
   5690 	data->oy -= ny;
   5691 
   5692 	if (data->searchmark != NULL && !data->timeout)
   5693 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
   5694 	window_copy_update_selection(wme, 0, 0);
   5695 
   5696 	screen_write_start_pane(&ctx, wp, NULL);
   5697 	screen_write_cursormove(&ctx, 0, 0, 0);
   5698 	screen_write_deleteline(&ctx, ny, 8);
   5699 	window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny);
   5700 	window_copy_write_line(wme, &ctx, 0);
   5701 	if (screen_size_y(s) > 1)
   5702 		window_copy_write_line(wme, &ctx, 1);
   5703 	if (screen_size_y(s) > 3)
   5704 		window_copy_write_line(wme, &ctx, screen_size_y(s) - 2);
   5705 	if (s->sel != NULL && screen_size_y(s) > ny)
   5706 		window_copy_write_line(wme, &ctx, screen_size_y(s) - ny - 1);
   5707 	screen_write_cursormove(&ctx, data->cx, data->cy, 0);
   5708 	screen_write_stop(&ctx);
   5709 	wp->flags |= PANE_REDRAWSCROLLBAR;
   5710 }
   5711 
   5712 static void
   5713 window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
   5714 {
   5715 	struct window_pane		*wp = wme->wp;
   5716 	struct window_copy_mode_data	*data = wme->data;
   5717 	struct screen			*s = &data->screen;
   5718 	struct screen_write_ctx		 ctx;
   5719 
   5720 	if (ny > screen_hsize(data->backing))
   5721 		return;
   5722 
   5723 	if (data->oy > screen_hsize(data->backing) - ny)
   5724 		ny = screen_hsize(data->backing) - data->oy;
   5725 	if (ny == 0)
   5726 		return;
   5727 	data->oy += ny;
   5728 
   5729 	if (data->searchmark != NULL && !data->timeout)
   5730 		window_copy_search_marks(wme, NULL, data->searchregex, 1);
   5731 	window_copy_update_selection(wme, 0, 0);
   5732 
   5733 	screen_write_start_pane(&ctx, wp, NULL);
   5734 	screen_write_cursormove(&ctx, 0, 0, 0);
   5735 	screen_write_insertline(&ctx, ny, 8);
   5736 	window_copy_write_lines(wme, &ctx, 0, ny);
   5737 	if (s->sel != NULL && screen_size_y(s) > ny)
   5738 		window_copy_write_line(wme, &ctx, ny);
   5739 	else if (ny == 1) /* nuke position */
   5740 		window_copy_write_line(wme, &ctx, 1);
   5741 	screen_write_cursormove(&ctx, data->cx, data->cy, 0);
   5742 	screen_write_stop(&ctx);
   5743 	wp->flags |= PANE_REDRAWSCROLLBAR;
   5744 }
   5745 
   5746 static void
   5747 window_copy_rectangle_set(struct window_mode_entry *wme, int rectflag)
   5748 {
   5749 	struct window_copy_mode_data	*data = wme->data;
   5750 	u_int				 px, py;
   5751 
   5752 	data->rectflag = rectflag;
   5753 
   5754 	py = screen_hsize(data->backing) + data->cy - data->oy;
   5755 	px = window_copy_find_length(wme, py);
   5756 	if (data->cx > px)
   5757 		window_copy_update_cursor(wme, px, data->cy);
   5758 
   5759 	window_copy_update_selection(wme, 1, 0);
   5760 	window_copy_redraw_screen(wme);
   5761 }
   5762 
   5763 static void
   5764 window_copy_move_mouse(struct mouse_event *m)
   5765 {
   5766 	struct window_pane		*wp;
   5767 	struct window_mode_entry	*wme;
   5768 	u_int				 x, y;
   5769 
   5770 	wp = cmd_mouse_pane(m, NULL, NULL);
   5771 	if (wp == NULL)
   5772 		return;
   5773 	wme = TAILQ_FIRST(&wp->modes);
   5774 	if (wme == NULL)
   5775 		return;
   5776 	if (wme->mode != &window_copy_mode && wme->mode != &window_view_mode)
   5777 		return;
   5778 
   5779 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
   5780 		return;
   5781 
   5782 	window_copy_update_cursor(wme, x, y);
   5783 }
   5784 
   5785 void
   5786 window_copy_start_drag(struct client *c, struct mouse_event *m)
   5787 {
   5788 	struct window_pane		*wp;
   5789 	struct window_mode_entry	*wme;
   5790 	struct window_copy_mode_data	*data;
   5791 	u_int				 x, y, yg;
   5792 
   5793 	if (c == NULL)
   5794 		return;
   5795 
   5796 	wp = cmd_mouse_pane(m, NULL, NULL);
   5797 	if (wp == NULL)
   5798 		return;
   5799 	wme = TAILQ_FIRST(&wp->modes);
   5800 	if (wme == NULL)
   5801 		return;
   5802 	if (wme->mode != &window_copy_mode && wme->mode != &window_view_mode)
   5803 		return;
   5804 
   5805 	if (cmd_mouse_at(wp, m, &x, &y, 1) != 0)
   5806 		return;
   5807 
   5808 	c->tty.mouse_drag_update = window_copy_drag_update;
   5809 	c->tty.mouse_drag_release = window_copy_drag_release;
   5810 
   5811 	data = wme->data;
   5812 	yg = screen_hsize(data->backing) + y - data->oy;
   5813 	if (x < data->selrx || x > data->endselrx || yg != data->selry)
   5814 		data->selflag = SEL_CHAR;
   5815 	switch (data->selflag) {
   5816 	case SEL_WORD:
   5817 		if (data->separators != NULL) {
   5818 			window_copy_update_cursor(wme, x, y);
   5819 			window_copy_cursor_previous_word_pos(wme,
   5820 			    data->separators, &x, &y);
   5821 			y -= screen_hsize(data->backing) - data->oy;
   5822 		}
   5823 		window_copy_update_cursor(wme, x, y);
   5824 		break;
   5825 	case SEL_LINE:
   5826 		window_copy_update_cursor(wme, 0, y);
   5827 		break;
   5828 	case SEL_CHAR:
   5829 		window_copy_update_cursor(wme, x, y);
   5830 		window_copy_start_selection(wme);
   5831 		break;
   5832 	}
   5833 
   5834 	window_copy_redraw_screen(wme);
   5835 	window_copy_drag_update(c, m);
   5836 }
   5837 
   5838 static void
   5839 window_copy_drag_update(struct client *c, struct mouse_event *m)
   5840 {
   5841 	struct window_pane		*wp;
   5842 	struct window_mode_entry	*wme;
   5843 	struct window_copy_mode_data	*data;
   5844 	u_int				 x, y, old_cx, old_cy;
   5845 	struct timeval			 tv = {
   5846 		.tv_usec = WINDOW_COPY_DRAG_REPEAT_TIME
   5847 	};
   5848 
   5849 	if (c == NULL)
   5850 		return;
   5851 
   5852 	wp = cmd_mouse_pane(m, NULL, NULL);
   5853 	if (wp == NULL)
   5854 		return;
   5855 	wme = TAILQ_FIRST(&wp->modes);
   5856 	if (wme == NULL)
   5857 		return;
   5858 	if (wme->mode != &window_copy_mode && wme->mode != &window_view_mode)
   5859 		return;
   5860 
   5861 	data = wme->data;
   5862 	evtimer_del(&data->dragtimer);
   5863 
   5864 	if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
   5865 		return;
   5866 	old_cx = data->cx;
   5867 	old_cy = data->cy;
   5868 
   5869 	window_copy_update_cursor(wme, x, y);
   5870 	if (window_copy_update_selection(wme, 1, 0))
   5871 		window_copy_redraw_selection(wme, old_cy);
   5872 	if (old_cy != data->cy || old_cx == data->cx) {
   5873 		if (y == 0) {
   5874 			evtimer_add(&data->dragtimer, &tv);
   5875 			window_copy_cursor_up(wme, 1);
   5876 		} else if (y == screen_size_y(&data->screen) - 1) {
   5877 			evtimer_add(&data->dragtimer, &tv);
   5878 			window_copy_cursor_down(wme, 1);
   5879 		}
   5880 	}
   5881 }
   5882 
   5883 static void
   5884 window_copy_drag_release(struct client *c, struct mouse_event *m)
   5885 {
   5886 	struct window_pane		*wp;
   5887 	struct window_mode_entry	*wme;
   5888 	struct window_copy_mode_data	*data;
   5889 
   5890 	if (c == NULL)
   5891 		return;
   5892 
   5893 	wp = cmd_mouse_pane(m, NULL, NULL);
   5894 	if (wp == NULL)
   5895 		return;
   5896 	wme = TAILQ_FIRST(&wp->modes);
   5897 	if (wme == NULL)
   5898 		return;
   5899 	if (wme->mode != &window_copy_mode && wme->mode != &window_view_mode)
   5900 		return;
   5901 
   5902 	data = wme->data;
   5903 	evtimer_del(&data->dragtimer);
   5904 }
   5905 
   5906 static void
   5907 window_copy_jump_to_mark(struct window_mode_entry *wme)
   5908 {
   5909 	struct window_copy_mode_data	*data = wme->data;
   5910 	u_int				 tmx, tmy;
   5911 
   5912 	tmx = data->cx;
   5913 	tmy = screen_hsize(data->backing) + data->cy - data->oy;
   5914 	data->cx = data->mx;
   5915 	if (data->my < screen_hsize(data->backing)) {
   5916 		data->cy = 0;
   5917 		data->oy = screen_hsize(data->backing) - data->my;
   5918 	} else {
   5919 		data->cy = data->my - screen_hsize(data->backing);
   5920 		data->oy = 0;
   5921 	}
   5922 	data->mx = tmx;
   5923 	data->my = tmy;
   5924 	data->showmark = 1;
   5925 	window_copy_update_selection(wme, 0, 0);
   5926 	window_copy_redraw_screen(wme);
   5927 }
   5928 
   5929 /* Scroll up if the cursor went off the visible screen. */
   5930 static void
   5931 window_copy_acquire_cursor_up(struct window_mode_entry *wme, u_int hsize,
   5932     u_int oy, u_int oldy, u_int px, u_int py)
   5933 {
   5934 	u_int	cy, yy, ny, nd;
   5935 
   5936 	yy = hsize - oy;
   5937 	if (py < yy) {
   5938 		ny = yy - py;
   5939 		cy = 0;
   5940 		nd = 1;
   5941 	} else {
   5942 		ny = 0;
   5943 		cy = py - yy;
   5944 		nd = oldy - cy + 1;
   5945 	}
   5946 	while (ny > 0) {
   5947 		window_copy_cursor_up(wme, 1);
   5948 		ny--;
   5949 	}
   5950 	window_copy_update_cursor(wme, px, cy);
   5951 	if (window_copy_update_selection(wme, 1, 0))
   5952 		window_copy_redraw_lines(wme, cy, nd);
   5953 }
   5954 
   5955 /* Scroll down if the cursor went off the visible screen. */
   5956 static void
   5957 window_copy_acquire_cursor_down(struct window_mode_entry *wme, u_int hsize,
   5958     u_int sy, u_int oy, u_int oldy, u_int px, u_int py, int no_reset)
   5959 {
   5960 	u_int	cy, yy, ny, nd;
   5961 
   5962 	cy = py - hsize + oy;
   5963 	yy = sy - 1;
   5964 	if (cy > yy) {
   5965 		ny = cy - yy;
   5966 		oldy = yy;
   5967 		nd = 1;
   5968 	} else {
   5969 		ny = 0;
   5970 		nd = cy - oldy + 1;
   5971 	}
   5972 	while (ny > 0) {
   5973 	  window_copy_cursor_down(wme, 1);
   5974 	  ny--;
   5975 	}
   5976 	if (cy > yy)
   5977 		window_copy_update_cursor(wme, px, yy);
   5978 	else
   5979 		window_copy_update_cursor(wme, px, cy);
   5980 	if (window_copy_update_selection(wme, 1, no_reset))
   5981 		window_copy_redraw_lines(wme, oldy, nd);
   5982 }
   5983