4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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.
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.
19 #include <sys/types.h>
29 struct window_copy_mode_data
;
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 void window_copy_scroll1(struct window_mode_entry
*,
44 struct window_pane
*wp
, int, u_int
, int);
45 static void window_copy_pageup1(struct window_mode_entry
*, int);
46 static int window_copy_pagedown1(struct window_mode_entry
*, int, int);
47 static void window_copy_next_paragraph(struct window_mode_entry
*);
48 static void window_copy_previous_paragraph(struct window_mode_entry
*);
49 static void window_copy_redraw_selection(struct window_mode_entry
*, u_int
);
50 static void window_copy_redraw_lines(struct window_mode_entry
*, u_int
,
52 static void window_copy_redraw_screen(struct window_mode_entry
*);
53 static void window_copy_write_line(struct window_mode_entry
*,
54 struct screen_write_ctx
*, u_int
);
55 static void window_copy_write_lines(struct window_mode_entry
*,
56 struct screen_write_ctx
*, u_int
, u_int
);
57 static char *window_copy_match_at_cursor(struct window_copy_mode_data
*);
58 static void window_copy_scroll_to(struct window_mode_entry
*, u_int
, u_int
,
60 static int window_copy_search_compare(struct grid
*, u_int
, u_int
,
61 struct grid
*, u_int
, int);
62 static int window_copy_search_lr(struct grid
*, struct grid
*, u_int
*,
63 u_int
, u_int
, u_int
, int);
64 static int window_copy_search_rl(struct grid
*, struct grid
*, u_int
*,
65 u_int
, u_int
, u_int
, int);
66 static int window_copy_last_regex(struct grid
*, u_int
, u_int
, u_int
,
67 u_int
, u_int
*, u_int
*, const char *, const regex_t
*,
69 static int window_copy_search_mark_at(struct window_copy_mode_data
*,
70 u_int
, u_int
, u_int
*);
71 static char *window_copy_stringify(struct grid
*, u_int
, u_int
, u_int
,
73 static void window_copy_cstrtocellpos(struct grid
*, u_int
, u_int
*,
74 u_int
*, const char *);
75 static int window_copy_search_marks(struct window_mode_entry
*,
76 struct screen
*, int, int);
77 static void window_copy_clear_marks(struct window_mode_entry
*);
78 static int window_copy_is_lowercase(const char *);
79 static void window_copy_search_back_overlap(struct grid
*, regex_t
*,
80 u_int
*, u_int
*, u_int
*, u_int
);
81 static int window_copy_search_jump(struct window_mode_entry
*,
82 struct grid
*, struct grid
*, u_int
, u_int
, u_int
, int, int,
84 static int window_copy_search(struct window_mode_entry
*, int, int);
85 static int window_copy_search_up(struct window_mode_entry
*, int);
86 static int window_copy_search_down(struct window_mode_entry
*, int);
87 static void window_copy_goto_line(struct window_mode_entry
*, const char *);
88 static void window_copy_update_cursor(struct window_mode_entry
*, u_int
,
90 static void window_copy_start_selection(struct window_mode_entry
*);
91 static int window_copy_adjust_selection(struct window_mode_entry
*,
93 static int window_copy_set_selection(struct window_mode_entry
*, int, int);
94 static int window_copy_update_selection(struct window_mode_entry
*, int,
96 static void window_copy_synchronize_cursor(struct window_mode_entry
*, int);
97 static void *window_copy_get_selection(struct window_mode_entry
*, size_t *);
98 static void window_copy_copy_buffer(struct window_mode_entry
*,
99 const char *, void *, size_t, int, int);
100 static void window_copy_pipe(struct window_mode_entry
*,
101 struct session
*, const char *);
102 static void window_copy_copy_pipe(struct window_mode_entry
*,
103 struct session
*, const char *, const char *,
105 static void window_copy_copy_selection(struct window_mode_entry
*,
106 const char *, int, int);
107 static void window_copy_append_selection(struct window_mode_entry
*);
108 static void window_copy_clear_selection(struct window_mode_entry
*);
109 static void window_copy_copy_line(struct window_mode_entry
*, char **,
110 size_t *, u_int
, u_int
, u_int
);
111 static int window_copy_in_set(struct window_mode_entry
*, u_int
, u_int
,
113 static u_int
window_copy_find_length(struct window_mode_entry
*, u_int
);
114 static void window_copy_cursor_start_of_line(struct window_mode_entry
*);
115 static void window_copy_cursor_back_to_indentation(
116 struct window_mode_entry
*);
117 static void window_copy_cursor_end_of_line(struct window_mode_entry
*);
118 static void window_copy_other_end(struct window_mode_entry
*);
119 static void window_copy_cursor_left(struct window_mode_entry
*);
120 static void window_copy_cursor_right(struct window_mode_entry
*, int);
121 static void window_copy_cursor_up(struct window_mode_entry
*, int);
122 static void window_copy_cursor_down(struct window_mode_entry
*, int);
123 static void window_copy_cursor_jump(struct window_mode_entry
*);
124 static void window_copy_cursor_jump_back(struct window_mode_entry
*);
125 static void window_copy_cursor_jump_to(struct window_mode_entry
*);
126 static void window_copy_cursor_jump_to_back(struct window_mode_entry
*);
127 static void window_copy_cursor_next_word(struct window_mode_entry
*,
129 static void window_copy_cursor_next_word_end_pos(struct window_mode_entry
*,
130 const char *, u_int
*, u_int
*);
131 static void window_copy_cursor_next_word_end(struct window_mode_entry
*,
133 static void window_copy_cursor_previous_word_pos(struct window_mode_entry
*,
134 const char *, u_int
*, u_int
*);
135 static void window_copy_cursor_previous_word(struct window_mode_entry
*,
137 static void window_copy_cursor_prompt(struct window_mode_entry
*, int,
139 static void window_copy_scroll_up(struct window_mode_entry
*, u_int
);
140 static void window_copy_scroll_down(struct window_mode_entry
*, u_int
);
141 static void window_copy_rectangle_set(struct window_mode_entry
*, int);
142 static void window_copy_move_mouse(struct mouse_event
*);
143 static void window_copy_drag_update(struct client
*, struct mouse_event
*);
144 static void window_copy_drag_release(struct client
*, struct mouse_event
*);
145 static void window_copy_jump_to_mark(struct window_mode_entry
*);
146 static void window_copy_acquire_cursor_up(struct window_mode_entry
*,
147 u_int
, u_int
, u_int
, u_int
, u_int
);
148 static void window_copy_acquire_cursor_down(struct window_mode_entry
*,
149 u_int
, u_int
, u_int
, u_int
, u_int
, u_int
, int);
150 static u_int
window_copy_clip_width(u_int
, u_int
, u_int
, u_int
);
151 static u_int
window_copy_search_mark_match(struct window_copy_mode_data
*,
152 u_int
, u_int
, u_int
, int);
154 const struct window_mode window_copy_mode
= {
157 .init
= window_copy_init
,
158 .free
= window_copy_free
,
159 .resize
= window_copy_resize
,
160 .key_table
= window_copy_key_table
,
161 .command
= window_copy_command
,
162 .formats
= window_copy_formats
,
165 const struct window_mode window_view_mode
= {
168 .init
= window_copy_view_init
,
169 .free
= window_copy_free
,
170 .resize
= window_copy_resize
,
171 .key_table
= window_copy_key_table
,
172 .command
= window_copy_command
,
173 .formats
= window_copy_formats
,
178 WINDOW_COPY_SEARCHUP
,
179 WINDOW_COPY_SEARCHDOWN
,
180 WINDOW_COPY_JUMPFORWARD
,
181 WINDOW_COPY_JUMPBACKWARD
,
182 WINDOW_COPY_JUMPTOFORWARD
,
183 WINDOW_COPY_JUMPTOBACKWARD
,
187 WINDOW_COPY_REL_POS_ABOVE
,
188 WINDOW_COPY_REL_POS_ON_SCREEN
,
189 WINDOW_COPY_REL_POS_BELOW
,
192 enum window_copy_cmd_action
{
193 WINDOW_COPY_CMD_NOTHING
,
194 WINDOW_COPY_CMD_REDRAW
,
195 WINDOW_COPY_CMD_CANCEL
,
198 enum window_copy_cmd_clear
{
199 WINDOW_COPY_CMD_CLEAR_ALWAYS
,
200 WINDOW_COPY_CMD_CLEAR_NEVER
,
201 WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
204 struct window_copy_cmd_state
{
205 struct window_mode_entry
*wme
;
208 struct mouse_event
*m
;
216 * Copy mode's visible screen (the "screen" field) is filled from one of two
217 * sources: the original contents of the pane (used when we actually enter via
218 * the "copy-mode" command, to copy the contents of the current pane), or else
219 * a series of lines containing the output from an output-writing tmux command
220 * (such as any of the "show-*" or "list-*" commands).
222 * In either case, the full content of the copy-mode grid is pointed at by the
223 * "backing" field, and is copied into "screen" as needed (that is, when
224 * scrolling occurs). When copy-mode is backed by a pane, backing points
225 * directly at that pane's screen structure (&wp->base); when backed by a list
226 * of output-lines from a command, it points at a newly-allocated screen
227 * structure (which is deallocated when the mode ends).
229 struct window_copy_mode_data
{
230 struct screen screen
;
232 struct screen
*backing
;
233 int backing_written
; /* backing display started */
234 struct screen
*writing
;
235 struct input_ctx
*ictx
;
237 int viewmode
; /* view mode entered */
239 u_int oy
; /* number of lines scrolled up */
241 u_int selx
; /* beginning of selection */
244 u_int endselx
; /* end of selection */
248 CURSORDRAG_NONE
, /* selection is independent of cursor */
249 CURSORDRAG_ENDSEL
, /* end is synchronized with cursor */
250 CURSORDRAG_SEL
, /* start is synchronized with cursor */
258 } lineflag
; /* line selection mode */
259 int rectflag
; /* in rectangle copy mode? */
260 int scroll_exit
; /* exit on scroll to end? */
261 int hide_position
; /* hide position marker */
264 SEL_CHAR
, /* select one char at a time */
265 SEL_WORD
, /* select one word at a time */
266 SEL_LINE
, /* select one line at a time */
269 const char *separators
; /* word separators */
271 u_int dx
; /* drag start position */
274 u_int selrx
; /* selection reset positions */
282 u_int lastcx
; /* position in last line w/ content */
283 u_int lastsx
; /* size of last line w/ content */
285 u_int mx
; /* mark position */
302 int timeout
; /* search has timed out */
303 #define WINDOW_COPY_SEARCH_TIMEOUT 10000
304 #define WINDOW_COPY_SEARCH_ALL_TIMEOUT 200
305 #define WINDOW_COPY_SEARCH_MAX_LINE 2000
308 struct utf8_data
*jumpchar
;
310 struct event dragtimer
;
311 #define WINDOW_COPY_DRAG_REPEAT_TIME 50000
315 window_copy_scroll_timer(__unused
int fd
, __unused
short events
, void *arg
)
317 struct window_mode_entry
*wme
= arg
;
318 struct window_pane
*wp
= wme
->wp
;
319 struct window_copy_mode_data
*data
= wme
->data
;
320 struct timeval tv
= {
321 .tv_usec
= WINDOW_COPY_DRAG_REPEAT_TIME
324 evtimer_del(&data
->dragtimer
);
326 if (TAILQ_FIRST(&wp
->modes
) != wme
)
330 evtimer_add(&data
->dragtimer
, &tv
);
331 window_copy_cursor_up(wme
, 1);
332 } else if (data
->cy
== screen_size_y(&data
->screen
) - 1) {
333 evtimer_add(&data
->dragtimer
, &tv
);
334 window_copy_cursor_down(wme
, 1);
338 static struct screen
*
339 window_copy_clone_screen(struct screen
*src
, struct screen
*hint
, u_int
*cx
,
343 const struct grid_line
*gl
;
347 dst
= xcalloc(1, sizeof *dst
);
349 sy
= screen_hsize(src
) + screen_size_y(src
);
351 while (sy
> screen_hsize(src
)) {
352 gl
= grid_peek_line(src
->grid
, sy
- 1);
353 if (gl
->cellused
!= 0)
358 log_debug("%s: target screen is %ux%u, source %ux%u", __func__
,
359 screen_size_x(src
), sy
, screen_size_x(hint
),
360 screen_hsize(src
) + screen_size_y(src
));
361 screen_init(dst
, screen_size_x(src
), sy
, screen_hlimit(src
));
364 * Ensure history is on for the backing grid so lines are not deleted
367 dst
->grid
->flags
|= GRID_HISTORY
;
368 grid_duplicate_lines(dst
->grid
, 0, src
->grid
, 0, sy
);
370 dst
->grid
->sy
= sy
- screen_hsize(src
);
371 dst
->grid
->hsize
= screen_hsize(src
);
372 dst
->grid
->hscrolled
= src
->grid
->hscrolled
;
373 if (src
->cy
> dst
->grid
->sy
- 1) {
375 dst
->cy
= dst
->grid
->sy
- 1;
381 if (cx
!= NULL
&& cy
!= NULL
) {
383 *cy
= screen_hsize(dst
) + dst
->cy
;
384 reflow
= (screen_size_x(hint
) != screen_size_x(dst
));
389 grid_wrap_position(dst
->grid
, *cx
, *cy
, &wx
, &wy
);
390 screen_resize_cursor(dst
, screen_size_x(hint
), screen_size_y(hint
), 1,
393 grid_unwrap_position(dst
->grid
, cx
, cy
, wx
, wy
);
398 static struct window_copy_mode_data
*
399 window_copy_common_init(struct window_mode_entry
*wme
)
401 struct window_pane
*wp
= wme
->wp
;
402 struct window_copy_mode_data
*data
;
403 struct screen
*base
= &wp
->base
;
405 wme
->data
= data
= xcalloc(1, sizeof *data
);
407 data
->cursordrag
= CURSORDRAG_NONE
;
408 data
->lineflag
= LINE_SEL_NONE
;
409 data
->selflag
= SEL_CHAR
;
411 if (wp
->searchstr
!= NULL
) {
412 data
->searchtype
= WINDOW_COPY_SEARCHUP
;
413 data
->searchregex
= wp
->searchregex
;
414 data
->searchstr
= xstrdup(wp
->searchstr
);
416 data
->searchtype
= WINDOW_COPY_OFF
;
417 data
->searchregex
= 0;
418 data
->searchstr
= NULL
;
420 data
->searchx
= data
->searchy
= data
->searcho
= -1;
423 data
->jumptype
= WINDOW_COPY_OFF
;
424 data
->jumpchar
= NULL
;
426 screen_init(&data
->screen
, screen_size_x(base
), screen_size_y(base
), 0);
427 screen_set_default_cursor(&data
->screen
, global_w_options
);
428 data
->modekeys
= options_get_number(wp
->window
->options
, "mode-keys");
430 evtimer_set(&data
->dragtimer
, window_copy_scroll_timer
, wme
);
435 static struct screen
*
436 window_copy_init(struct window_mode_entry
*wme
,
437 __unused
struct cmd_find_state
*fs
, struct args
*args
)
439 struct window_pane
*wp
= wme
->swp
;
440 struct window_copy_mode_data
*data
;
441 struct screen
*base
= &wp
->base
;
442 struct screen_write_ctx ctx
;
445 data
= window_copy_common_init(wme
);
446 data
->backing
= window_copy_clone_screen(base
, &data
->screen
, &cx
, &cy
,
447 wme
->swp
!= wme
->wp
);
450 if (cy
< screen_hsize(data
->backing
)) {
452 data
->oy
= screen_hsize(data
->backing
) - cy
;
454 data
->cy
= cy
- screen_hsize(data
->backing
);
458 data
->scroll_exit
= args_has(args
, 'e');
459 data
->hide_position
= args_has(args
, 'H');
461 if (base
->hyperlinks
!= NULL
)
462 data
->screen
.hyperlinks
= hyperlinks_copy(base
->hyperlinks
);
463 data
->screen
.cx
= data
->cx
;
464 data
->screen
.cy
= data
->cy
;
466 data
->my
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
469 screen_write_start(&ctx
, &data
->screen
);
470 for (i
= 0; i
< screen_size_y(&data
->screen
); i
++)
471 window_copy_write_line(wme
, &ctx
, i
);
472 screen_write_cursormove(&ctx
, data
->cx
, data
->cy
, 0);
473 screen_write_stop(&ctx
);
475 return (&data
->screen
);
478 static struct screen
*
479 window_copy_view_init(struct window_mode_entry
*wme
,
480 __unused
struct cmd_find_state
*fs
, __unused
struct args
*args
)
482 struct window_pane
*wp
= wme
->wp
;
483 struct window_copy_mode_data
*data
;
484 struct screen
*base
= &wp
->base
;
485 u_int sx
= screen_size_x(base
);
487 data
= window_copy_common_init(wme
);
490 data
->backing
= xmalloc(sizeof *data
->backing
);
491 screen_init(data
->backing
, sx
, screen_size_y(base
), UINT_MAX
);
492 data
->writing
= xmalloc(sizeof *data
->writing
);
493 screen_init(data
->writing
, sx
, screen_size_y(base
), 0);
494 data
->ictx
= input_init(NULL
, NULL
, NULL
);
496 data
->my
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
499 return (&data
->screen
);
503 window_copy_free(struct window_mode_entry
*wme
)
505 struct window_copy_mode_data
*data
= wme
->data
;
507 evtimer_del(&data
->dragtimer
);
509 free(data
->searchmark
);
510 free(data
->searchstr
);
511 free(data
->jumpchar
);
513 if (data
->writing
!= NULL
) {
514 screen_free(data
->writing
);
517 if (data
->ictx
!= NULL
)
518 input_free(data
->ictx
);
519 screen_free(data
->backing
);
522 screen_free(&data
->screen
);
527 window_copy_add(struct window_pane
*wp
, int parse
, const char *fmt
, ...)
532 window_copy_vadd(wp
, parse
, fmt
, ap
);
537 window_copy_init_ctx_cb(__unused
struct screen_write_ctx
*ctx
,
538 struct tty_ctx
*ttyctx
)
540 memcpy(&ttyctx
->defaults
, &grid_default_cell
, sizeof ttyctx
->defaults
);
541 ttyctx
->palette
= NULL
;
542 ttyctx
->redraw_cb
= NULL
;
543 ttyctx
->set_client_cb
= NULL
;
548 window_copy_vadd(struct window_pane
*wp
, int parse
, const char *fmt
, va_list ap
)
550 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
551 struct window_copy_mode_data
*data
= wme
->data
;
552 struct screen
*backing
= data
->backing
;
553 struct screen
*writing
= data
->writing
;
554 struct screen_write_ctx writing_ctx
, backing_ctx
, ctx
;
556 u_int old_hsize
, old_cy
;
557 u_int sx
= screen_size_x(backing
);
561 vasprintf(&text
, fmt
, ap
);
562 screen_write_start(&writing_ctx
, writing
);
563 screen_write_reset(&writing_ctx
);
564 input_parse_screen(data
->ictx
, writing
, window_copy_init_ctx_cb
,
565 data
, text
, strlen(text
));
569 old_hsize
= screen_hsize(data
->backing
);
570 screen_write_start(&backing_ctx
, backing
);
571 if (data
->backing_written
) {
573 * On the second or later line, do a CRLF before writing
574 * (so it's on a new line).
576 screen_write_carriagereturn(&backing_ctx
);
577 screen_write_linefeed(&backing_ctx
, 0, 8);
579 data
->backing_written
= 1;
580 old_cy
= backing
->cy
;
582 screen_write_fast_copy(&backing_ctx
, writing
, 0, 0, sx
, 1);
584 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
585 screen_write_vnputs(&backing_ctx
, 0, &gc
, fmt
, ap
);
587 screen_write_stop(&backing_ctx
);
589 data
->oy
+= screen_hsize(data
->backing
) - old_hsize
;
591 screen_write_start_pane(&ctx
, wp
, &data
->screen
);
594 * If the history has changed, draw the top line.
595 * (If there's any history at all, it has changed.)
597 if (screen_hsize(data
->backing
))
598 window_copy_redraw_lines(wme
, 0, 1);
600 /* Write the new lines. */
601 window_copy_redraw_lines(wme
, old_cy
, backing
->cy
- old_cy
+ 1);
603 screen_write_stop(&ctx
);
607 window_copy_scroll(struct window_pane
*wp
, int sl_mpos
, u_int my
,
610 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
613 window_set_active_pane(wp
->window
, wp
, 0);
614 window_copy_scroll1(wme
, wp
, sl_mpos
, my
, scroll_exit
);
619 window_copy_scroll1(struct window_mode_entry
*wme
, struct window_pane
*wp
,
620 int sl_mpos
, u_int my
, int scroll_exit
)
622 struct window_copy_mode_data
*data
= wme
->data
;
623 u_int ox
, oy
, px
, py
, n
, offset
, size
;
625 u_int slider_height
= wp
->sb_slider_h
;
626 u_int sb_height
= wp
->sy
, sb_top
= wp
->yoff
;
627 u_int sy
= screen_size_y(data
->backing
);
628 int new_slider_y
, delta
;
631 * sl_mpos is where in the slider the user is dragging, mouse is
632 * dragging this y point relative to top of slider.
634 if (my
<= sb_top
+ sl_mpos
) {
635 /* Slider banged into top. */
636 new_slider_y
= sb_top
- wp
->yoff
;
637 } else if (my
- sl_mpos
> sb_top
+ sb_height
- slider_height
) {
638 /* Slider banged into bottom. */
639 new_slider_y
= sb_top
- wp
->yoff
+ (sb_height
- slider_height
);
641 /* Slider is somewhere in the middle. */
642 new_slider_y
= my
- wp
->yoff
- sl_mpos
+ 1;
645 if (TAILQ_FIRST(&wp
->modes
) == NULL
||
646 window_copy_get_current_offset(wp
, &offset
, &size
) == 0)
650 * See screen_redraw_draw_pane_scrollbar - this is the inverse of the
651 * formula used there.
653 new_offset
= new_slider_y
* ((float)(size
+ sb_height
) / sb_height
);
654 delta
= (int)offset
- new_offset
;
657 * Move pane view around based on delta relative to the cursor,
658 * maintaining the selection.
660 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
661 ox
= window_copy_find_length(wme
, oy
);
663 if (data
->cx
!= ox
) {
664 data
->lastcx
= data
->cx
;
667 data
->cx
= data
->lastcx
;
671 if (data
->oy
+ n
> screen_hsize(data
->backing
)) {
672 data
->oy
= screen_hsize(data
->backing
);
683 if (data
->cy
+ (n
- data
->oy
) >= sy
)
686 data
->cy
+= n
- data
->oy
;
691 /* Don't also drag tail when dragging a scrollbar, it looks weird. */
692 data
->cursordrag
= CURSORDRAG_NONE
;
694 if (data
->screen
.sel
== NULL
|| !data
->rectflag
) {
695 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
696 px
= window_copy_find_length(wme
, py
);
697 if ((data
->cx
>= data
->lastsx
&& data
->cx
!= px
) ||
699 window_copy_cursor_end_of_line(wme
);
702 if (scroll_exit
&& data
->oy
== 0) {
703 window_pane_reset_mode(wp
);
707 if (data
->searchmark
!= NULL
&& !data
->timeout
)
708 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
709 window_copy_update_selection(wme
, 1, 0);
710 window_copy_redraw_screen(wme
);
714 window_copy_pageup(struct window_pane
*wp
, int half_page
)
716 window_copy_pageup1(TAILQ_FIRST(&wp
->modes
), half_page
);
720 window_copy_pageup1(struct window_mode_entry
*wme
, int half_page
)
722 struct window_copy_mode_data
*data
= wme
->data
;
723 struct screen
*s
= &data
->screen
;
724 u_int n
, ox
, oy
, px
, py
;
726 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
727 ox
= window_copy_find_length(wme
, oy
);
729 if (data
->cx
!= ox
) {
730 data
->lastcx
= data
->cx
;
733 data
->cx
= data
->lastcx
;
736 if (screen_size_y(s
) > 2) {
738 n
= screen_size_y(s
) / 2;
740 n
= screen_size_y(s
) - 2;
743 if (data
->oy
+ n
> screen_hsize(data
->backing
)) {
744 data
->oy
= screen_hsize(data
->backing
);
752 if (data
->screen
.sel
== NULL
|| !data
->rectflag
) {
753 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
754 px
= window_copy_find_length(wme
, py
);
755 if ((data
->cx
>= data
->lastsx
&& data
->cx
!= px
) ||
757 window_copy_cursor_end_of_line(wme
);
760 if (data
->searchmark
!= NULL
&& !data
->timeout
)
761 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
762 window_copy_update_selection(wme
, 1, 0);
763 window_copy_redraw_screen(wme
);
767 window_copy_pagedown(struct window_pane
*wp
, int half_page
, int scroll_exit
)
769 if (window_copy_pagedown1(TAILQ_FIRST(&wp
->modes
), half_page
,
771 window_pane_reset_mode(wp
);
777 window_copy_pagedown1(struct window_mode_entry
*wme
, int half_page
,
780 struct window_copy_mode_data
*data
= wme
->data
;
781 struct screen
*s
= &data
->screen
;
782 u_int n
, ox
, oy
, px
, py
;
784 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
785 ox
= window_copy_find_length(wme
, oy
);
787 if (data
->cx
!= ox
) {
788 data
->lastcx
= data
->cx
;
791 data
->cx
= data
->lastcx
;
794 if (screen_size_y(s
) > 2) {
796 n
= screen_size_y(s
) / 2;
798 n
= screen_size_y(s
) - 2;
803 if (data
->cy
+ (n
- data
->oy
) >= screen_size_y(data
->backing
))
804 data
->cy
= screen_size_y(data
->backing
) - 1;
806 data
->cy
+= n
- data
->oy
;
810 if (data
->screen
.sel
== NULL
|| !data
->rectflag
) {
811 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
812 px
= window_copy_find_length(wme
, py
);
813 if ((data
->cx
>= data
->lastsx
&& data
->cx
!= px
) ||
815 window_copy_cursor_end_of_line(wme
);
818 if (scroll_exit
&& data
->oy
== 0)
820 if (data
->searchmark
!= NULL
&& !data
->timeout
)
821 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
822 window_copy_update_selection(wme
, 1, 0);
823 window_copy_redraw_screen(wme
);
828 window_copy_previous_paragraph(struct window_mode_entry
*wme
)
830 struct window_copy_mode_data
*data
= wme
->data
;
833 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
835 while (oy
> 0 && window_copy_find_length(wme
, oy
) == 0)
838 while (oy
> 0 && window_copy_find_length(wme
, oy
) > 0)
841 window_copy_scroll_to(wme
, 0, oy
, 0);
845 window_copy_next_paragraph(struct window_mode_entry
*wme
)
847 struct window_copy_mode_data
*data
= wme
->data
;
848 struct screen
*s
= &data
->screen
;
851 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
852 maxy
= screen_hsize(data
->backing
) + screen_size_y(s
) - 1;
854 while (oy
< maxy
&& window_copy_find_length(wme
, oy
) == 0)
857 while (oy
< maxy
&& window_copy_find_length(wme
, oy
) > 0)
860 ox
= window_copy_find_length(wme
, oy
);
861 window_copy_scroll_to(wme
, ox
, oy
, 0);
865 window_copy_get_word(struct window_pane
*wp
, u_int x
, u_int y
)
867 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
868 struct window_copy_mode_data
*data
= wme
->data
;
869 struct grid
*gd
= data
->screen
.grid
;
871 return (format_grid_word(gd
, x
, gd
->hsize
+ y
));
875 window_copy_get_line(struct window_pane
*wp
, u_int y
)
877 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
878 struct window_copy_mode_data
*data
= wme
->data
;
879 struct grid
*gd
= data
->screen
.grid
;
881 return (format_grid_line(gd
, gd
->hsize
+ y
));
885 window_copy_cursor_hyperlink_cb(struct format_tree
*ft
)
887 struct window_pane
*wp
= format_get_pane(ft
);
888 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
889 struct window_copy_mode_data
*data
= wme
->data
;
890 struct grid
*gd
= data
->screen
.grid
;
892 return (format_grid_hyperlink(gd
, data
->cx
, gd
->hsize
+ data
->cy
,
897 window_copy_cursor_word_cb(struct format_tree
*ft
)
899 struct window_pane
*wp
= format_get_pane(ft
);
900 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
901 struct window_copy_mode_data
*data
= wme
->data
;
903 return (window_copy_get_word(wp
, data
->cx
, data
->cy
));
907 window_copy_cursor_line_cb(struct format_tree
*ft
)
909 struct window_pane
*wp
= format_get_pane(ft
);
910 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
911 struct window_copy_mode_data
*data
= wme
->data
;
913 return (window_copy_get_line(wp
, data
->cy
));
917 window_copy_search_match_cb(struct format_tree
*ft
)
919 struct window_pane
*wp
= format_get_pane(ft
);
920 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
921 struct window_copy_mode_data
*data
= wme
->data
;
923 return (window_copy_match_at_cursor(data
));
927 window_copy_formats(struct window_mode_entry
*wme
, struct format_tree
*ft
)
929 struct window_copy_mode_data
*data
= wme
->data
;
930 u_int hsize
= screen_hsize(data
->backing
);
931 struct grid_line
*gl
;
933 gl
= grid_get_line(data
->backing
->grid
, hsize
- data
->oy
);
934 format_add(ft
, "top_line_time", "%llu", (unsigned long long)gl
->time
);
936 format_add(ft
, "scroll_position", "%d", data
->oy
);
937 format_add(ft
, "rectangle_toggle", "%d", data
->rectflag
);
939 format_add(ft
, "copy_cursor_x", "%d", data
->cx
);
940 format_add(ft
, "copy_cursor_y", "%d", data
->cy
);
942 if (data
->screen
.sel
!= NULL
) {
943 format_add(ft
, "selection_start_x", "%d", data
->selx
);
944 format_add(ft
, "selection_start_y", "%d", data
->sely
);
945 format_add(ft
, "selection_end_x", "%d", data
->endselx
);
946 format_add(ft
, "selection_end_y", "%d", data
->endsely
);
948 if (data
->cursordrag
!= CURSORDRAG_NONE
)
949 format_add(ft
, "selection_active", "1");
951 format_add(ft
, "selection_active", "0");
952 if (data
->endselx
!= data
->selx
|| data
->endsely
!= data
->sely
)
953 format_add(ft
, "selection_present", "1");
955 format_add(ft
, "selection_present", "0");
957 format_add(ft
, "selection_active", "0");
958 format_add(ft
, "selection_present", "0");
961 format_add(ft
, "search_present", "%d", data
->searchmark
!= NULL
);
962 format_add(ft
, "search_timed_out", "%d", data
->timeout
);
963 if (data
->searchcount
!= -1) {
964 format_add(ft
, "search_count", "%d", data
->searchcount
);
965 format_add(ft
, "search_count_partial", "%d", data
->searchmore
);
967 format_add_cb(ft
, "search_match", window_copy_search_match_cb
);
969 format_add_cb(ft
, "copy_cursor_word", window_copy_cursor_word_cb
);
970 format_add_cb(ft
, "copy_cursor_line", window_copy_cursor_line_cb
);
971 format_add_cb(ft
, "copy_cursor_hyperlink",
972 window_copy_cursor_hyperlink_cb
);
976 window_copy_size_changed(struct window_mode_entry
*wme
)
978 struct window_copy_mode_data
*data
= wme
->data
;
979 struct screen
*s
= &data
->screen
;
980 struct screen_write_ctx ctx
;
981 int search
= (data
->searchmark
!= NULL
);
983 window_copy_clear_selection(wme
);
984 window_copy_clear_marks(wme
);
986 screen_write_start(&ctx
, s
);
987 window_copy_write_lines(wme
, &ctx
, 0, screen_size_y(s
));
988 screen_write_stop(&ctx
);
990 if (search
&& !data
->timeout
)
991 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 0);
992 data
->searchx
= data
->cx
;
993 data
->searchy
= data
->cy
;
994 data
->searcho
= data
->oy
;
998 window_copy_resize(struct window_mode_entry
*wme
, u_int sx
, u_int sy
)
1000 struct window_copy_mode_data
*data
= wme
->data
;
1001 struct screen
*s
= &data
->screen
;
1002 struct grid
*gd
= data
->backing
->grid
;
1003 u_int cx
, cy
, wx
, wy
;
1006 screen_resize(s
, sx
, sy
, 0);
1008 cy
= gd
->hsize
+ data
->cy
- data
->oy
;
1009 reflow
= (gd
->sx
!= sx
);
1011 grid_wrap_position(gd
, cx
, cy
, &wx
, &wy
);
1012 screen_resize_cursor(data
->backing
, sx
, sy
, 1, 0, 0);
1014 grid_unwrap_position(gd
, &cx
, &cy
, wx
, wy
);
1017 if (cy
< gd
->hsize
) {
1019 data
->oy
= gd
->hsize
- cy
;
1021 data
->cy
= cy
- gd
->hsize
;
1025 window_copy_size_changed(wme
);
1026 window_copy_redraw_screen(wme
);
1030 window_copy_key_table(struct window_mode_entry
*wme
)
1032 struct window_pane
*wp
= wme
->wp
;
1034 if (options_get_number(wp
->window
->options
, "mode-keys") == MODEKEY_VI
)
1035 return ("copy-mode-vi");
1036 return ("copy-mode");
1040 window_copy_expand_search_string(struct window_copy_cmd_state
*cs
)
1042 struct window_mode_entry
*wme
= cs
->wme
;
1043 struct window_copy_mode_data
*data
= wme
->data
;
1044 const char *ss
= args_string(cs
->wargs
, 0);
1047 if (ss
== NULL
|| *ss
== '\0')
1050 if (args_has(cs
->args
, 'F')) {
1051 expanded
= format_single(NULL
, ss
, NULL
, NULL
, NULL
, wme
->wp
);
1052 if (*expanded
== '\0') {
1056 free(data
->searchstr
);
1057 data
->searchstr
= expanded
;
1059 free(data
->searchstr
);
1060 data
->searchstr
= xstrdup(ss
);
1065 static enum window_copy_cmd_action
1066 window_copy_cmd_append_selection(struct window_copy_cmd_state
*cs
)
1068 struct window_mode_entry
*wme
= cs
->wme
;
1069 struct session
*s
= cs
->s
;
1072 window_copy_append_selection(wme
);
1073 window_copy_clear_selection(wme
);
1074 return (WINDOW_COPY_CMD_REDRAW
);
1077 static enum window_copy_cmd_action
1078 window_copy_cmd_append_selection_and_cancel(struct window_copy_cmd_state
*cs
)
1080 struct window_mode_entry
*wme
= cs
->wme
;
1081 struct session
*s
= cs
->s
;
1084 window_copy_append_selection(wme
);
1085 window_copy_clear_selection(wme
);
1086 return (WINDOW_COPY_CMD_CANCEL
);
1089 static enum window_copy_cmd_action
1090 window_copy_cmd_back_to_indentation(struct window_copy_cmd_state
*cs
)
1092 struct window_mode_entry
*wme
= cs
->wme
;
1094 window_copy_cursor_back_to_indentation(wme
);
1095 return (WINDOW_COPY_CMD_NOTHING
);
1098 static enum window_copy_cmd_action
1099 window_copy_cmd_begin_selection(struct window_copy_cmd_state
*cs
)
1101 struct window_mode_entry
*wme
= cs
->wme
;
1102 struct client
*c
= cs
->c
;
1103 struct mouse_event
*m
= cs
->m
;
1104 struct window_copy_mode_data
*data
= wme
->data
;
1107 window_copy_start_drag(c
, m
);
1108 return (WINDOW_COPY_CMD_NOTHING
);
1111 data
->lineflag
= LINE_SEL_NONE
;
1112 data
->selflag
= SEL_CHAR
;
1113 window_copy_start_selection(wme
);
1114 return (WINDOW_COPY_CMD_REDRAW
);
1117 static enum window_copy_cmd_action
1118 window_copy_cmd_stop_selection(struct window_copy_cmd_state
*cs
)
1120 struct window_mode_entry
*wme
= cs
->wme
;
1121 struct window_copy_mode_data
*data
= wme
->data
;
1123 data
->cursordrag
= CURSORDRAG_NONE
;
1124 data
->lineflag
= LINE_SEL_NONE
;
1125 data
->selflag
= SEL_CHAR
;
1126 return (WINDOW_COPY_CMD_NOTHING
);
1129 static enum window_copy_cmd_action
1130 window_copy_cmd_bottom_line(struct window_copy_cmd_state
*cs
)
1132 struct window_mode_entry
*wme
= cs
->wme
;
1133 struct window_copy_mode_data
*data
= wme
->data
;
1136 data
->cy
= screen_size_y(&data
->screen
) - 1;
1138 window_copy_update_selection(wme
, 1, 0);
1139 return (WINDOW_COPY_CMD_REDRAW
);
1142 static enum window_copy_cmd_action
1143 window_copy_cmd_cancel(__unused
struct window_copy_cmd_state
*cs
)
1145 return (WINDOW_COPY_CMD_CANCEL
);
1148 static enum window_copy_cmd_action
1149 window_copy_cmd_clear_selection(struct window_copy_cmd_state
*cs
)
1151 struct window_mode_entry
*wme
= cs
->wme
;
1153 window_copy_clear_selection(wme
);
1154 return (WINDOW_COPY_CMD_REDRAW
);
1157 static enum window_copy_cmd_action
1158 window_copy_do_copy_end_of_line(struct window_copy_cmd_state
*cs
, int pipe
,
1161 struct window_mode_entry
*wme
= cs
->wme
;
1162 struct client
*c
= cs
->c
;
1163 struct session
*s
= cs
->s
;
1164 struct winlink
*wl
= cs
->wl
;
1165 struct window_pane
*wp
= wme
->wp
;
1166 u_int count
= args_count(cs
->wargs
);
1167 u_int np
= wme
->prefix
, ocx
, ocy
, ooy
;
1168 struct window_copy_mode_data
*data
= wme
->data
;
1169 char *prefix
= NULL
, *command
= NULL
;
1170 const char *arg0
= args_string(cs
->wargs
, 0);
1171 const char *arg1
= args_string(cs
->wargs
, 1);
1172 int set_paste
= !args_has(cs
->wargs
, 'P');
1173 int set_clip
= !args_has(cs
->wargs
, 'C');
1177 prefix
= format_single(NULL
, arg1
, c
, s
, wl
, wp
);
1178 if (s
!= NULL
&& count
> 0 && *arg0
!= '\0')
1179 command
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
1182 prefix
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
1189 window_copy_start_selection(wme
);
1190 for (; np
> 1; np
--)
1191 window_copy_cursor_down(wme
, 0);
1192 window_copy_cursor_end_of_line(wme
);
1196 window_copy_copy_pipe(wme
, s
, prefix
, command
,
1197 set_paste
, set_clip
);
1199 window_copy_copy_selection(wme
, prefix
,
1200 set_paste
, set_clip
);
1205 return (WINDOW_COPY_CMD_CANCEL
);
1208 window_copy_clear_selection(wme
);
1216 return (WINDOW_COPY_CMD_REDRAW
);
1219 static enum window_copy_cmd_action
1220 window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state
*cs
)
1222 return (window_copy_do_copy_end_of_line(cs
, 0, 0));
1225 static enum window_copy_cmd_action
1226 window_copy_cmd_copy_end_of_line_and_cancel(struct window_copy_cmd_state
*cs
)
1228 return (window_copy_do_copy_end_of_line(cs
, 0, 1));
1231 static enum window_copy_cmd_action
1232 window_copy_cmd_copy_pipe_end_of_line(struct window_copy_cmd_state
*cs
)
1234 return (window_copy_do_copy_end_of_line(cs
, 1, 0));
1237 static enum window_copy_cmd_action
1238 window_copy_cmd_copy_pipe_end_of_line_and_cancel(
1239 struct window_copy_cmd_state
*cs
)
1241 return (window_copy_do_copy_end_of_line(cs
, 1, 1));
1244 static enum window_copy_cmd_action
1245 window_copy_do_copy_line(struct window_copy_cmd_state
*cs
, int pipe
, int cancel
)
1247 struct window_mode_entry
*wme
= cs
->wme
;
1248 struct client
*c
= cs
->c
;
1249 struct session
*s
= cs
->s
;
1250 struct winlink
*wl
= cs
->wl
;
1251 struct window_pane
*wp
= wme
->wp
;
1252 struct window_copy_mode_data
*data
= wme
->data
;
1253 u_int count
= args_count(cs
->wargs
);
1254 u_int np
= wme
->prefix
, ocx
, ocy
, ooy
;
1255 char *prefix
= NULL
, *command
= NULL
;
1256 const char *arg0
= args_string(cs
->wargs
, 0);
1257 const char *arg1
= args_string(cs
->wargs
, 1);
1258 int set_paste
= !args_has(cs
->wargs
, 'P');
1259 int set_clip
= !args_has(cs
->wargs
, 'C');
1263 prefix
= format_single(NULL
, arg1
, c
, s
, wl
, wp
);
1264 if (s
!= NULL
&& count
> 0 && *arg0
!= '\0')
1265 command
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
1268 prefix
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
1275 data
->selflag
= SEL_CHAR
;
1276 window_copy_cursor_start_of_line(wme
);
1277 window_copy_start_selection(wme
);
1278 for (; np
> 1; np
--)
1279 window_copy_cursor_down(wme
, 0);
1280 window_copy_cursor_end_of_line(wme
);
1284 window_copy_copy_pipe(wme
, s
, prefix
, command
,
1285 set_paste
, set_clip
);
1287 window_copy_copy_selection(wme
, prefix
,
1288 set_paste
, set_clip
);
1293 return (WINDOW_COPY_CMD_CANCEL
);
1296 window_copy_clear_selection(wme
);
1304 return (WINDOW_COPY_CMD_REDRAW
);
1307 static enum window_copy_cmd_action
1308 window_copy_cmd_copy_line(struct window_copy_cmd_state
*cs
)
1310 return (window_copy_do_copy_line(cs
, 0, 0));
1313 static enum window_copy_cmd_action
1314 window_copy_cmd_copy_line_and_cancel(struct window_copy_cmd_state
*cs
)
1316 return (window_copy_do_copy_line(cs
, 0, 1));
1319 static enum window_copy_cmd_action
1320 window_copy_cmd_copy_pipe_line(struct window_copy_cmd_state
*cs
)
1322 return (window_copy_do_copy_line(cs
, 1, 0));
1325 static enum window_copy_cmd_action
1326 window_copy_cmd_copy_pipe_line_and_cancel(struct window_copy_cmd_state
*cs
)
1328 return (window_copy_do_copy_line(cs
, 1, 1));
1331 static enum window_copy_cmd_action
1332 window_copy_cmd_copy_selection_no_clear(struct window_copy_cmd_state
*cs
)
1334 struct window_mode_entry
*wme
= cs
->wme
;
1335 struct client
*c
= cs
->c
;
1336 struct session
*s
= cs
->s
;
1337 struct winlink
*wl
= cs
->wl
;
1338 struct window_pane
*wp
= wme
->wp
;
1339 char *prefix
= NULL
;
1340 const char *arg0
= args_string(cs
->wargs
, 0);
1341 int set_paste
= !args_has(cs
->wargs
, 'P');
1342 int set_clip
= !args_has(cs
->wargs
, 'C');
1345 prefix
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
1348 window_copy_copy_selection(wme
, prefix
, set_paste
, set_clip
);
1351 return (WINDOW_COPY_CMD_NOTHING
);
1354 static enum window_copy_cmd_action
1355 window_copy_cmd_copy_selection(struct window_copy_cmd_state
*cs
)
1357 struct window_mode_entry
*wme
= cs
->wme
;
1359 window_copy_cmd_copy_selection_no_clear(cs
);
1360 window_copy_clear_selection(wme
);
1361 return (WINDOW_COPY_CMD_REDRAW
);
1364 static enum window_copy_cmd_action
1365 window_copy_cmd_copy_selection_and_cancel(struct window_copy_cmd_state
*cs
)
1367 struct window_mode_entry
*wme
= cs
->wme
;
1369 window_copy_cmd_copy_selection_no_clear(cs
);
1370 window_copy_clear_selection(wme
);
1371 return (WINDOW_COPY_CMD_CANCEL
);
1374 static enum window_copy_cmd_action
1375 window_copy_cmd_cursor_down(struct window_copy_cmd_state
*cs
)
1377 struct window_mode_entry
*wme
= cs
->wme
;
1378 u_int np
= wme
->prefix
;
1380 for (; np
!= 0; np
--)
1381 window_copy_cursor_down(wme
, 0);
1382 return (WINDOW_COPY_CMD_NOTHING
);
1385 static enum window_copy_cmd_action
1386 window_copy_cmd_cursor_down_and_cancel(struct window_copy_cmd_state
*cs
)
1388 struct window_mode_entry
*wme
= cs
->wme
;
1389 struct window_copy_mode_data
*data
= wme
->data
;
1390 u_int np
= wme
->prefix
, cy
;
1393 for (; np
!= 0; np
--)
1394 window_copy_cursor_down(wme
, 0);
1395 if (cy
== data
->cy
&& data
->oy
== 0)
1396 return (WINDOW_COPY_CMD_CANCEL
);
1397 return (WINDOW_COPY_CMD_NOTHING
);
1400 static enum window_copy_cmd_action
1401 window_copy_cmd_cursor_left(struct window_copy_cmd_state
*cs
)
1403 struct window_mode_entry
*wme
= cs
->wme
;
1404 u_int np
= wme
->prefix
;
1406 for (; np
!= 0; np
--)
1407 window_copy_cursor_left(wme
);
1408 return (WINDOW_COPY_CMD_NOTHING
);
1411 static enum window_copy_cmd_action
1412 window_copy_cmd_cursor_right(struct window_copy_cmd_state
*cs
)
1414 struct window_mode_entry
*wme
= cs
->wme
;
1415 struct window_copy_mode_data
*data
= wme
->data
;
1416 u_int np
= wme
->prefix
;
1418 for (; np
!= 0; np
--) {
1419 window_copy_cursor_right(wme
, data
->screen
.sel
!= NULL
&&
1422 return (WINDOW_COPY_CMD_NOTHING
);
1425 /* Scroll line containing the cursor to the given position. */
1426 static enum window_copy_cmd_action
1427 window_copy_cmd_scroll_to(struct window_copy_cmd_state
*cs
, u_int to
)
1429 struct window_mode_entry
*wme
= cs
->wme
;
1430 struct window_copy_mode_data
*data
= wme
->data
;
1432 int scroll_up
; /* >0 up, <0 down */
1434 scroll_up
= data
->cy
- to
;
1435 delta
= abs(scroll_up
);
1436 oy
= screen_hsize(data
->backing
) - data
->oy
;
1439 * oy is the maximum scroll down amount, while data->oy is the maximum
1442 if (scroll_up
> 0 && data
->oy
>= delta
) {
1443 window_copy_scroll_up(wme
, delta
);
1445 } else if (scroll_up
< 0 && oy
>= delta
) {
1446 window_copy_scroll_down(wme
, delta
);
1450 window_copy_update_selection(wme
, 0, 0);
1451 return (WINDOW_COPY_CMD_REDRAW
);
1454 /* Scroll line containing the cursor to the bottom. */
1455 static enum window_copy_cmd_action
1456 window_copy_cmd_scroll_bottom(struct window_copy_cmd_state
*cs
)
1458 struct window_copy_mode_data
*data
= cs
->wme
->data
;
1461 bottom
= screen_size_y(&data
->screen
) - 1;
1462 return (window_copy_cmd_scroll_to(cs
, bottom
));
1465 /* Scroll line containing the cursor to the middle. */
1466 static enum window_copy_cmd_action
1467 window_copy_cmd_scroll_middle(struct window_copy_cmd_state
*cs
)
1469 struct window_copy_mode_data
*data
= cs
->wme
->data
;
1472 mid_value
= (screen_size_y(&data
->screen
) - 1) / 2;
1473 return (window_copy_cmd_scroll_to(cs
, mid_value
));
1476 /* Scroll line containing the cursor to the top. */
1477 static enum window_copy_cmd_action
1478 window_copy_cmd_scroll_top(struct window_copy_cmd_state
*cs
)
1480 return (window_copy_cmd_scroll_to(cs
, 0));
1483 static enum window_copy_cmd_action
1484 window_copy_cmd_cursor_up(struct window_copy_cmd_state
*cs
)
1486 struct window_mode_entry
*wme
= cs
->wme
;
1487 u_int np
= wme
->prefix
;
1489 for (; np
!= 0; np
--)
1490 window_copy_cursor_up(wme
, 0);
1491 return (WINDOW_COPY_CMD_NOTHING
);
1494 static enum window_copy_cmd_action
1495 window_copy_cmd_end_of_line(struct window_copy_cmd_state
*cs
)
1497 struct window_mode_entry
*wme
= cs
->wme
;
1499 window_copy_cursor_end_of_line(wme
);
1500 return (WINDOW_COPY_CMD_NOTHING
);
1503 static enum window_copy_cmd_action
1504 window_copy_cmd_halfpage_down(struct window_copy_cmd_state
*cs
)
1506 struct window_mode_entry
*wme
= cs
->wme
;
1507 struct window_copy_mode_data
*data
= wme
->data
;
1508 u_int np
= wme
->prefix
;
1510 for (; np
!= 0; np
--) {
1511 if (window_copy_pagedown1(wme
, 1, data
->scroll_exit
))
1512 return (WINDOW_COPY_CMD_CANCEL
);
1514 return (WINDOW_COPY_CMD_NOTHING
);
1517 static enum window_copy_cmd_action
1518 window_copy_cmd_halfpage_down_and_cancel(struct window_copy_cmd_state
*cs
)
1521 struct window_mode_entry
*wme
= cs
->wme
;
1522 u_int np
= wme
->prefix
;
1524 for (; np
!= 0; np
--) {
1525 if (window_copy_pagedown1(wme
, 1, 1))
1526 return (WINDOW_COPY_CMD_CANCEL
);
1528 return (WINDOW_COPY_CMD_NOTHING
);
1531 static enum window_copy_cmd_action
1532 window_copy_cmd_halfpage_up(struct window_copy_cmd_state
*cs
)
1534 struct window_mode_entry
*wme
= cs
->wme
;
1535 u_int np
= wme
->prefix
;
1537 for (; np
!= 0; np
--)
1538 window_copy_pageup1(wme
, 1);
1539 return (WINDOW_COPY_CMD_NOTHING
);
1542 static enum window_copy_cmd_action
1543 window_copy_cmd_toggle_position(struct window_copy_cmd_state
*cs
)
1545 struct window_mode_entry
*wme
= cs
->wme
;
1546 struct window_copy_mode_data
*data
= wme
->data
;
1548 data
->hide_position
= !data
->hide_position
;
1549 return (WINDOW_COPY_CMD_REDRAW
);
1552 static enum window_copy_cmd_action
1553 window_copy_cmd_history_bottom(struct window_copy_cmd_state
*cs
)
1555 struct window_mode_entry
*wme
= cs
->wme
;
1556 struct window_copy_mode_data
*data
= wme
->data
;
1557 struct screen
*s
= data
->backing
;
1560 oy
= screen_hsize(s
) + data
->cy
- data
->oy
;
1561 if (data
->lineflag
== LINE_SEL_RIGHT_LEFT
&& oy
== data
->endsely
)
1562 window_copy_other_end(wme
);
1564 data
->cy
= screen_size_y(&data
->screen
) - 1;
1565 data
->cx
= window_copy_find_length(wme
, screen_hsize(s
) + data
->cy
);
1568 if (data
->searchmark
!= NULL
&& !data
->timeout
)
1569 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
1570 window_copy_update_selection(wme
, 1, 0);
1571 return (WINDOW_COPY_CMD_REDRAW
);
1574 static enum window_copy_cmd_action
1575 window_copy_cmd_history_top(struct window_copy_cmd_state
*cs
)
1577 struct window_mode_entry
*wme
= cs
->wme
;
1578 struct window_copy_mode_data
*data
= wme
->data
;
1581 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
1582 if (data
->lineflag
== LINE_SEL_LEFT_RIGHT
&& oy
== data
->sely
)
1583 window_copy_other_end(wme
);
1587 data
->oy
= screen_hsize(data
->backing
);
1589 if (data
->searchmark
!= NULL
&& !data
->timeout
)
1590 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
1591 window_copy_update_selection(wme
, 1, 0);
1592 return (WINDOW_COPY_CMD_REDRAW
);
1595 static enum window_copy_cmd_action
1596 window_copy_cmd_jump_again(struct window_copy_cmd_state
*cs
)
1598 struct window_mode_entry
*wme
= cs
->wme
;
1599 struct window_copy_mode_data
*data
= wme
->data
;
1600 u_int np
= wme
->prefix
;
1602 switch (data
->jumptype
) {
1603 case WINDOW_COPY_JUMPFORWARD
:
1604 for (; np
!= 0; np
--)
1605 window_copy_cursor_jump(wme
);
1607 case WINDOW_COPY_JUMPBACKWARD
:
1608 for (; np
!= 0; np
--)
1609 window_copy_cursor_jump_back(wme
);
1611 case WINDOW_COPY_JUMPTOFORWARD
:
1612 for (; np
!= 0; np
--)
1613 window_copy_cursor_jump_to(wme
);
1615 case WINDOW_COPY_JUMPTOBACKWARD
:
1616 for (; np
!= 0; np
--)
1617 window_copy_cursor_jump_to_back(wme
);
1620 return (WINDOW_COPY_CMD_NOTHING
);
1623 static enum window_copy_cmd_action
1624 window_copy_cmd_jump_reverse(struct window_copy_cmd_state
*cs
)
1626 struct window_mode_entry
*wme
= cs
->wme
;
1627 struct window_copy_mode_data
*data
= wme
->data
;
1628 u_int np
= wme
->prefix
;
1630 switch (data
->jumptype
) {
1631 case WINDOW_COPY_JUMPFORWARD
:
1632 for (; np
!= 0; np
--)
1633 window_copy_cursor_jump_back(wme
);
1635 case WINDOW_COPY_JUMPBACKWARD
:
1636 for (; np
!= 0; np
--)
1637 window_copy_cursor_jump(wme
);
1639 case WINDOW_COPY_JUMPTOFORWARD
:
1640 for (; np
!= 0; np
--)
1641 window_copy_cursor_jump_to_back(wme
);
1643 case WINDOW_COPY_JUMPTOBACKWARD
:
1644 for (; np
!= 0; np
--)
1645 window_copy_cursor_jump_to(wme
);
1648 return (WINDOW_COPY_CMD_NOTHING
);
1651 static enum window_copy_cmd_action
1652 window_copy_cmd_middle_line(struct window_copy_cmd_state
*cs
)
1654 struct window_mode_entry
*wme
= cs
->wme
;
1655 struct window_copy_mode_data
*data
= wme
->data
;
1658 data
->cy
= (screen_size_y(&data
->screen
) - 1) / 2;
1660 window_copy_update_selection(wme
, 1, 0);
1661 return (WINDOW_COPY_CMD_REDRAW
);
1664 static enum window_copy_cmd_action
1665 window_copy_cmd_previous_matching_bracket(struct window_copy_cmd_state
*cs
)
1667 struct window_mode_entry
*wme
= cs
->wme
;
1668 u_int np
= wme
->prefix
;
1669 struct window_copy_mode_data
*data
= wme
->data
;
1670 struct screen
*s
= data
->backing
;
1671 char open
[] = "{[(", close
[] = "}])";
1672 char tried
, found
, start
, *cp
;
1673 u_int px
, py
, xx
, n
;
1674 struct grid_cell gc
;
1677 for (; np
!= 0; np
--) {
1678 /* Get cursor position and line length. */
1680 py
= screen_hsize(s
) + data
->cy
- data
->oy
;
1681 xx
= window_copy_find_length(wme
, py
);
1686 * Get the current character. If not on a bracket, try the
1687 * previous. If still not, then behave like previous-word.
1691 grid_get_cell(s
->grid
, px
, py
, &gc
);
1692 if (gc
.data
.size
!= 1 || (gc
.flags
& GRID_FLAG_PADDING
))
1695 found
= *gc
.data
.data
;
1696 cp
= strchr(close
, found
);
1699 if (data
->modekeys
== MODEKEY_EMACS
) {
1700 if (!tried
&& px
> 0) {
1705 window_copy_cursor_previous_word(wme
, close
, 1);
1709 start
= open
[cp
- close
];
1711 /* Walk backward until the matching bracket is reached. */
1722 xx
= window_copy_find_length(wme
, py
);
1723 } while (xx
== 0 && py
> 0);
1724 if (xx
== 0 && py
== 0) {
1732 grid_get_cell(s
->grid
, px
, py
, &gc
);
1733 if (gc
.data
.size
== 1 &&
1734 (~gc
.flags
& GRID_FLAG_PADDING
)) {
1735 if (*gc
.data
.data
== found
)
1737 else if (*gc
.data
.data
== start
)
1742 /* Move the cursor to the found location if any. */
1744 window_copy_scroll_to(wme
, px
, py
, 0);
1747 return (WINDOW_COPY_CMD_NOTHING
);
1750 static enum window_copy_cmd_action
1751 window_copy_cmd_next_matching_bracket(struct window_copy_cmd_state
*cs
)
1753 struct window_mode_entry
*wme
= cs
->wme
;
1754 u_int np
= wme
->prefix
;
1755 struct window_copy_mode_data
*data
= wme
->data
;
1756 struct screen
*s
= data
->backing
;
1757 char open
[] = "{[(", close
[] = "}])";
1758 char tried
, found
, end
, *cp
;
1759 u_int px
, py
, xx
, yy
, sx
, sy
, n
;
1760 struct grid_cell gc
;
1762 struct grid_line
*gl
;
1764 for (; np
!= 0; np
--) {
1765 /* Get cursor position and line length. */
1767 py
= screen_hsize(s
) + data
->cy
- data
->oy
;
1768 xx
= window_copy_find_length(wme
, py
);
1769 yy
= screen_hsize(s
) + screen_size_y(s
) - 1;
1774 * Get the current character. If not on a bracket, try the
1775 * next. If still not, then behave like next-word.
1779 grid_get_cell(s
->grid
, px
, py
, &gc
);
1780 if (gc
.data
.size
!= 1 || (gc
.flags
& GRID_FLAG_PADDING
))
1783 found
= *gc
.data
.data
;
1786 * In vi mode, attempt to move to previous bracket if a
1787 * closing bracket is found first. If this fails,
1788 * return to the original cursor position.
1790 cp
= strchr(close
, found
);
1791 if (cp
!= NULL
&& data
->modekeys
== MODEKEY_VI
) {
1793 sy
= screen_hsize(s
) + data
->cy
- data
->oy
;
1795 window_copy_scroll_to(wme
, px
, py
, 0);
1796 window_copy_cmd_previous_matching_bracket(cs
);
1799 py
= screen_hsize(s
) + data
->cy
- data
->oy
;
1800 grid_get_cell(s
->grid
, px
, py
, &gc
);
1801 if (gc
.data
.size
== 1 &&
1802 (~gc
.flags
& GRID_FLAG_PADDING
) &&
1803 strchr(close
, *gc
.data
.data
) != NULL
)
1804 window_copy_scroll_to(wme
, sx
, sy
, 0);
1808 cp
= strchr(open
, found
);
1811 if (data
->modekeys
== MODEKEY_EMACS
) {
1812 if (!tried
&& px
<= xx
) {
1817 window_copy_cursor_next_word_end(wme
, open
, 0);
1820 /* For vi, continue searching for bracket until EOL. */
1824 gl
= grid_get_line(s
->grid
, py
);
1825 if (~gl
->flags
& GRID_LINE_WRAPPED
)
1827 if (gl
->cellsize
> s
->grid
->sx
)
1831 xx
= window_copy_find_length(wme
, py
);
1836 end
= close
[cp
- open
];
1838 /* Walk forward until the matching bracket is reached. */
1849 xx
= window_copy_find_length(wme
, py
);
1853 grid_get_cell(s
->grid
, px
, py
, &gc
);
1854 if (gc
.data
.size
== 1 &&
1855 (~gc
.flags
& GRID_FLAG_PADDING
)) {
1856 if (*gc
.data
.data
== found
)
1858 else if (*gc
.data
.data
== end
)
1863 /* Move the cursor to the found location if any. */
1865 window_copy_scroll_to(wme
, px
, py
, 0);
1868 return (WINDOW_COPY_CMD_NOTHING
);
1871 static enum window_copy_cmd_action
1872 window_copy_cmd_next_paragraph(struct window_copy_cmd_state
*cs
)
1874 struct window_mode_entry
*wme
= cs
->wme
;
1875 u_int np
= wme
->prefix
;
1877 for (; np
!= 0; np
--)
1878 window_copy_next_paragraph(wme
);
1879 return (WINDOW_COPY_CMD_NOTHING
);
1882 static enum window_copy_cmd_action
1883 window_copy_cmd_next_space(struct window_copy_cmd_state
*cs
)
1885 struct window_mode_entry
*wme
= cs
->wme
;
1886 u_int np
= wme
->prefix
;
1888 for (; np
!= 0; np
--)
1889 window_copy_cursor_next_word(wme
, "");
1890 return (WINDOW_COPY_CMD_NOTHING
);
1893 static enum window_copy_cmd_action
1894 window_copy_cmd_next_space_end(struct window_copy_cmd_state
*cs
)
1896 struct window_mode_entry
*wme
= cs
->wme
;
1897 u_int np
= wme
->prefix
;
1899 for (; np
!= 0; np
--)
1900 window_copy_cursor_next_word_end(wme
, "", 0);
1901 return (WINDOW_COPY_CMD_NOTHING
);
1904 static enum window_copy_cmd_action
1905 window_copy_cmd_next_word(struct window_copy_cmd_state
*cs
)
1907 struct window_mode_entry
*wme
= cs
->wme
;
1908 u_int np
= wme
->prefix
;
1909 const char *separators
;
1911 separators
= options_get_string(cs
->s
->options
, "word-separators");
1913 for (; np
!= 0; np
--)
1914 window_copy_cursor_next_word(wme
, separators
);
1915 return (WINDOW_COPY_CMD_NOTHING
);
1918 static enum window_copy_cmd_action
1919 window_copy_cmd_next_word_end(struct window_copy_cmd_state
*cs
)
1921 struct window_mode_entry
*wme
= cs
->wme
;
1922 u_int np
= wme
->prefix
;
1923 const char *separators
;
1925 separators
= options_get_string(cs
->s
->options
, "word-separators");
1927 for (; np
!= 0; np
--)
1928 window_copy_cursor_next_word_end(wme
, separators
, 0);
1929 return (WINDOW_COPY_CMD_NOTHING
);
1932 static enum window_copy_cmd_action
1933 window_copy_cmd_other_end(struct window_copy_cmd_state
*cs
)
1935 struct window_mode_entry
*wme
= cs
->wme
;
1936 u_int np
= wme
->prefix
;
1937 struct window_copy_mode_data
*data
= wme
->data
;
1939 data
->selflag
= SEL_CHAR
;
1941 window_copy_other_end(wme
);
1942 return (WINDOW_COPY_CMD_NOTHING
);
1945 static enum window_copy_cmd_action
1946 window_copy_cmd_page_down(struct window_copy_cmd_state
*cs
)
1948 struct window_mode_entry
*wme
= cs
->wme
;
1949 struct window_copy_mode_data
*data
= wme
->data
;
1950 u_int np
= wme
->prefix
;
1952 for (; np
!= 0; np
--) {
1953 if (window_copy_pagedown1(wme
, 0, data
->scroll_exit
))
1954 return (WINDOW_COPY_CMD_CANCEL
);
1956 return (WINDOW_COPY_CMD_NOTHING
);
1959 static enum window_copy_cmd_action
1960 window_copy_cmd_page_down_and_cancel(struct window_copy_cmd_state
*cs
)
1962 struct window_mode_entry
*wme
= cs
->wme
;
1963 u_int np
= wme
->prefix
;
1965 for (; np
!= 0; np
--) {
1966 if (window_copy_pagedown1(wme
, 0, 1))
1967 return (WINDOW_COPY_CMD_CANCEL
);
1969 return (WINDOW_COPY_CMD_NOTHING
);
1972 static enum window_copy_cmd_action
1973 window_copy_cmd_page_up(struct window_copy_cmd_state
*cs
)
1975 struct window_mode_entry
*wme
= cs
->wme
;
1976 u_int np
= wme
->prefix
;
1978 for (; np
!= 0; np
--)
1979 window_copy_pageup1(wme
, 0);
1980 return (WINDOW_COPY_CMD_NOTHING
);
1983 static enum window_copy_cmd_action
1984 window_copy_cmd_previous_paragraph(struct window_copy_cmd_state
*cs
)
1986 struct window_mode_entry
*wme
= cs
->wme
;
1987 u_int np
= wme
->prefix
;
1989 for (; np
!= 0; np
--)
1990 window_copy_previous_paragraph(wme
);
1991 return (WINDOW_COPY_CMD_NOTHING
);
1994 static enum window_copy_cmd_action
1995 window_copy_cmd_previous_space(struct window_copy_cmd_state
*cs
)
1997 struct window_mode_entry
*wme
= cs
->wme
;
1998 u_int np
= wme
->prefix
;
2000 for (; np
!= 0; np
--)
2001 window_copy_cursor_previous_word(wme
, "", 1);
2002 return (WINDOW_COPY_CMD_NOTHING
);
2005 static enum window_copy_cmd_action
2006 window_copy_cmd_previous_word(struct window_copy_cmd_state
*cs
)
2008 struct window_mode_entry
*wme
= cs
->wme
;
2009 u_int np
= wme
->prefix
;
2010 const char *separators
;
2012 separators
= options_get_string(cs
->s
->options
, "word-separators");
2014 for (; np
!= 0; np
--)
2015 window_copy_cursor_previous_word(wme
, separators
, 1);
2016 return (WINDOW_COPY_CMD_NOTHING
);
2019 static enum window_copy_cmd_action
2020 window_copy_cmd_rectangle_on(struct window_copy_cmd_state
*cs
)
2022 struct window_mode_entry
*wme
= cs
->wme
;
2023 struct window_copy_mode_data
*data
= wme
->data
;
2025 data
->lineflag
= LINE_SEL_NONE
;
2026 window_copy_rectangle_set(wme
, 1);
2028 return (WINDOW_COPY_CMD_NOTHING
);
2031 static enum window_copy_cmd_action
2032 window_copy_cmd_rectangle_off(struct window_copy_cmd_state
*cs
)
2034 struct window_mode_entry
*wme
= cs
->wme
;
2035 struct window_copy_mode_data
*data
= wme
->data
;
2037 data
->lineflag
= LINE_SEL_NONE
;
2038 window_copy_rectangle_set(wme
, 0);
2040 return (WINDOW_COPY_CMD_NOTHING
);
2043 static enum window_copy_cmd_action
2044 window_copy_cmd_rectangle_toggle(struct window_copy_cmd_state
*cs
)
2046 struct window_mode_entry
*wme
= cs
->wme
;
2047 struct window_copy_mode_data
*data
= wme
->data
;
2049 data
->lineflag
= LINE_SEL_NONE
;
2050 window_copy_rectangle_set(wme
, !data
->rectflag
);
2052 return (WINDOW_COPY_CMD_NOTHING
);
2055 static enum window_copy_cmd_action
2056 window_copy_cmd_scroll_down(struct window_copy_cmd_state
*cs
)
2058 struct window_mode_entry
*wme
= cs
->wme
;
2059 struct window_copy_mode_data
*data
= wme
->data
;
2060 u_int np
= wme
->prefix
;
2062 for (; np
!= 0; np
--)
2063 window_copy_cursor_down(wme
, 1);
2064 if (data
->scroll_exit
&& data
->oy
== 0)
2065 return (WINDOW_COPY_CMD_CANCEL
);
2066 return (WINDOW_COPY_CMD_NOTHING
);
2069 static enum window_copy_cmd_action
2070 window_copy_cmd_scroll_down_and_cancel(struct window_copy_cmd_state
*cs
)
2072 struct window_mode_entry
*wme
= cs
->wme
;
2073 struct window_copy_mode_data
*data
= wme
->data
;
2074 u_int np
= wme
->prefix
;
2076 for (; np
!= 0; np
--)
2077 window_copy_cursor_down(wme
, 1);
2079 return (WINDOW_COPY_CMD_CANCEL
);
2080 return (WINDOW_COPY_CMD_NOTHING
);
2083 static enum window_copy_cmd_action
2084 window_copy_cmd_scroll_up(struct window_copy_cmd_state
*cs
)
2086 struct window_mode_entry
*wme
= cs
->wme
;
2087 u_int np
= wme
->prefix
;
2089 for (; np
!= 0; np
--)
2090 window_copy_cursor_up(wme
, 1);
2091 return (WINDOW_COPY_CMD_NOTHING
);
2094 static enum window_copy_cmd_action
2095 window_copy_cmd_search_again(struct window_copy_cmd_state
*cs
)
2097 struct window_mode_entry
*wme
= cs
->wme
;
2098 struct window_copy_mode_data
*data
= wme
->data
;
2099 u_int np
= wme
->prefix
;
2101 if (data
->searchtype
== WINDOW_COPY_SEARCHUP
) {
2102 for (; np
!= 0; np
--)
2103 window_copy_search_up(wme
, data
->searchregex
);
2104 } else if (data
->searchtype
== WINDOW_COPY_SEARCHDOWN
) {
2105 for (; np
!= 0; np
--)
2106 window_copy_search_down(wme
, data
->searchregex
);
2108 return (WINDOW_COPY_CMD_NOTHING
);
2111 static enum window_copy_cmd_action
2112 window_copy_cmd_search_reverse(struct window_copy_cmd_state
*cs
)
2114 struct window_mode_entry
*wme
= cs
->wme
;
2115 struct window_copy_mode_data
*data
= wme
->data
;
2116 u_int np
= wme
->prefix
;
2118 if (data
->searchtype
== WINDOW_COPY_SEARCHUP
) {
2119 for (; np
!= 0; np
--)
2120 window_copy_search_down(wme
, data
->searchregex
);
2121 } else if (data
->searchtype
== WINDOW_COPY_SEARCHDOWN
) {
2122 for (; np
!= 0; np
--)
2123 window_copy_search_up(wme
, data
->searchregex
);
2125 return (WINDOW_COPY_CMD_NOTHING
);
2128 static enum window_copy_cmd_action
2129 window_copy_cmd_select_line(struct window_copy_cmd_state
*cs
)
2131 struct window_mode_entry
*wme
= cs
->wme
;
2132 struct window_copy_mode_data
*data
= wme
->data
;
2133 u_int np
= wme
->prefix
;
2135 data
->lineflag
= LINE_SEL_LEFT_RIGHT
;
2137 data
->selflag
= SEL_LINE
;
2138 data
->dx
= data
->cx
;
2139 data
->dy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2141 window_copy_cursor_start_of_line(wme
);
2142 data
->selrx
= data
->cx
;
2143 data
->selry
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2144 data
->endselry
= data
->selry
;
2145 window_copy_start_selection(wme
);
2146 window_copy_cursor_end_of_line(wme
);
2147 data
->endselry
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2148 data
->endselrx
= window_copy_find_length(wme
, data
->endselry
);
2149 for (; np
> 1; np
--) {
2150 window_copy_cursor_down(wme
, 0);
2151 window_copy_cursor_end_of_line(wme
);
2154 return (WINDOW_COPY_CMD_REDRAW
);
2157 static enum window_copy_cmd_action
2158 window_copy_cmd_select_word(struct window_copy_cmd_state
*cs
)
2160 struct window_mode_entry
*wme
= cs
->wme
;
2161 struct options
*session_options
= cs
->s
->options
;
2162 struct window_copy_mode_data
*data
= wme
->data
;
2163 u_int px
, py
, nextx
, nexty
;
2165 data
->lineflag
= LINE_SEL_LEFT_RIGHT
;
2167 data
->selflag
= SEL_WORD
;
2168 data
->dx
= data
->cx
;
2169 data
->dy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2171 data
->separators
= options_get_string(session_options
,
2173 window_copy_cursor_previous_word(wme
, data
->separators
, 0);
2175 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2178 window_copy_start_selection(wme
);
2180 /* Handle single character words. */
2183 if (grid_get_line(data
->backing
->grid
, nexty
)->flags
&
2184 GRID_LINE_WRAPPED
&& nextx
> screen_size_x(data
->backing
) - 1) {
2188 if (px
>= window_copy_find_length(wme
, py
) ||
2189 !window_copy_in_set(wme
, nextx
, nexty
, WHITESPACE
))
2190 window_copy_cursor_next_word_end(wme
, data
->separators
, 1);
2192 window_copy_update_cursor(wme
, px
, data
->cy
);
2193 if (window_copy_update_selection(wme
, 1, 1))
2194 window_copy_redraw_lines(wme
, data
->cy
, 1);
2196 data
->endselrx
= data
->cx
;
2197 data
->endselry
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2198 if (data
->dy
> data
->endselry
) {
2199 data
->dy
= data
->endselry
;
2200 data
->dx
= data
->endselrx
;
2201 } else if (data
->dx
> data
->endselrx
)
2202 data
->dx
= data
->endselrx
;
2204 return (WINDOW_COPY_CMD_REDRAW
);
2207 static enum window_copy_cmd_action
2208 window_copy_cmd_set_mark(struct window_copy_cmd_state
*cs
)
2210 struct window_copy_mode_data
*data
= cs
->wme
->data
;
2212 data
->mx
= data
->cx
;
2213 data
->my
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
2215 return (WINDOW_COPY_CMD_REDRAW
);
2218 static enum window_copy_cmd_action
2219 window_copy_cmd_start_of_line(struct window_copy_cmd_state
*cs
)
2221 struct window_mode_entry
*wme
= cs
->wme
;
2223 window_copy_cursor_start_of_line(wme
);
2224 return (WINDOW_COPY_CMD_NOTHING
);
2227 static enum window_copy_cmd_action
2228 window_copy_cmd_top_line(struct window_copy_cmd_state
*cs
)
2230 struct window_mode_entry
*wme
= cs
->wme
;
2231 struct window_copy_mode_data
*data
= wme
->data
;
2236 window_copy_update_selection(wme
, 1, 0);
2237 return (WINDOW_COPY_CMD_REDRAW
);
2240 static enum window_copy_cmd_action
2241 window_copy_cmd_copy_pipe_no_clear(struct window_copy_cmd_state
*cs
)
2243 struct window_mode_entry
*wme
= cs
->wme
;
2244 struct client
*c
= cs
->c
;
2245 struct session
*s
= cs
->s
;
2246 struct winlink
*wl
= cs
->wl
;
2247 struct window_pane
*wp
= wme
->wp
;
2248 char *command
= NULL
, *prefix
= NULL
;
2249 const char *arg0
= args_string(cs
->wargs
, 0);
2250 const char *arg1
= args_string(cs
->wargs
, 1);
2251 int set_paste
= !args_has(cs
->wargs
, 'P');
2252 int set_clip
= !args_has(cs
->wargs
, 'C');
2255 prefix
= format_single(NULL
, arg1
, c
, s
, wl
, wp
);
2257 if (s
!= NULL
&& arg0
!= NULL
&& *arg0
!= '\0')
2258 command
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
2259 window_copy_copy_pipe(wme
, s
, prefix
, command
,
2260 set_paste
, set_clip
);
2264 return (WINDOW_COPY_CMD_NOTHING
);
2267 static enum window_copy_cmd_action
2268 window_copy_cmd_copy_pipe(struct window_copy_cmd_state
*cs
)
2270 struct window_mode_entry
*wme
= cs
->wme
;
2272 window_copy_cmd_copy_pipe_no_clear(cs
);
2273 window_copy_clear_selection(wme
);
2274 return (WINDOW_COPY_CMD_REDRAW
);
2277 static enum window_copy_cmd_action
2278 window_copy_cmd_copy_pipe_and_cancel(struct window_copy_cmd_state
*cs
)
2280 struct window_mode_entry
*wme
= cs
->wme
;
2282 window_copy_cmd_copy_pipe_no_clear(cs
);
2283 window_copy_clear_selection(wme
);
2284 return (WINDOW_COPY_CMD_CANCEL
);
2287 static enum window_copy_cmd_action
2288 window_copy_cmd_pipe_no_clear(struct window_copy_cmd_state
*cs
)
2290 struct window_mode_entry
*wme
= cs
->wme
;
2291 struct client
*c
= cs
->c
;
2292 struct session
*s
= cs
->s
;
2293 struct winlink
*wl
= cs
->wl
;
2294 struct window_pane
*wp
= wme
->wp
;
2295 char *command
= NULL
;
2296 const char *arg0
= args_string(cs
->wargs
, 0);
2298 if (s
!= NULL
&& arg0
!= NULL
&& *arg0
!= '\0')
2299 command
= format_single(NULL
, arg0
, c
, s
, wl
, wp
);
2300 window_copy_pipe(wme
, s
, command
);
2303 return (WINDOW_COPY_CMD_NOTHING
);
2306 static enum window_copy_cmd_action
2307 window_copy_cmd_pipe(struct window_copy_cmd_state
*cs
)
2309 struct window_mode_entry
*wme
= cs
->wme
;
2311 window_copy_cmd_pipe_no_clear(cs
);
2312 window_copy_clear_selection(wme
);
2313 return (WINDOW_COPY_CMD_REDRAW
);
2316 static enum window_copy_cmd_action
2317 window_copy_cmd_pipe_and_cancel(struct window_copy_cmd_state
*cs
)
2319 struct window_mode_entry
*wme
= cs
->wme
;
2321 window_copy_cmd_pipe_no_clear(cs
);
2322 window_copy_clear_selection(wme
);
2323 return (WINDOW_COPY_CMD_CANCEL
);
2326 static enum window_copy_cmd_action
2327 window_copy_cmd_goto_line(struct window_copy_cmd_state
*cs
)
2329 struct window_mode_entry
*wme
= cs
->wme
;
2330 const char *arg0
= args_string(cs
->wargs
, 0);
2333 window_copy_goto_line(wme
, arg0
);
2334 return (WINDOW_COPY_CMD_NOTHING
);
2337 static enum window_copy_cmd_action
2338 window_copy_cmd_jump_backward(struct window_copy_cmd_state
*cs
)
2340 struct window_mode_entry
*wme
= cs
->wme
;
2341 struct window_copy_mode_data
*data
= wme
->data
;
2342 u_int np
= wme
->prefix
;
2343 const char *arg0
= args_string(cs
->wargs
, 0);
2345 if (*arg0
!= '\0') {
2346 data
->jumptype
= WINDOW_COPY_JUMPBACKWARD
;
2347 free(data
->jumpchar
);
2348 data
->jumpchar
= utf8_fromcstr(arg0
);
2349 for (; np
!= 0; np
--)
2350 window_copy_cursor_jump_back(wme
);
2352 return (WINDOW_COPY_CMD_NOTHING
);
2355 static enum window_copy_cmd_action
2356 window_copy_cmd_jump_forward(struct window_copy_cmd_state
*cs
)
2358 struct window_mode_entry
*wme
= cs
->wme
;
2359 struct window_copy_mode_data
*data
= wme
->data
;
2360 u_int np
= wme
->prefix
;
2361 const char *arg0
= args_string(cs
->wargs
, 0);
2363 if (*arg0
!= '\0') {
2364 data
->jumptype
= WINDOW_COPY_JUMPFORWARD
;
2365 free(data
->jumpchar
);
2366 data
->jumpchar
= utf8_fromcstr(arg0
);
2367 for (; np
!= 0; np
--)
2368 window_copy_cursor_jump(wme
);
2370 return (WINDOW_COPY_CMD_NOTHING
);
2373 static enum window_copy_cmd_action
2374 window_copy_cmd_jump_to_backward(struct window_copy_cmd_state
*cs
)
2376 struct window_mode_entry
*wme
= cs
->wme
;
2377 struct window_copy_mode_data
*data
= wme
->data
;
2378 u_int np
= wme
->prefix
;
2379 const char *arg0
= args_string(cs
->wargs
, 0);
2381 if (*arg0
!= '\0') {
2382 data
->jumptype
= WINDOW_COPY_JUMPTOBACKWARD
;
2383 free(data
->jumpchar
);
2384 data
->jumpchar
= utf8_fromcstr(arg0
);
2385 for (; np
!= 0; np
--)
2386 window_copy_cursor_jump_to_back(wme
);
2388 return (WINDOW_COPY_CMD_NOTHING
);
2391 static enum window_copy_cmd_action
2392 window_copy_cmd_jump_to_forward(struct window_copy_cmd_state
*cs
)
2394 struct window_mode_entry
*wme
= cs
->wme
;
2395 struct window_copy_mode_data
*data
= wme
->data
;
2396 u_int np
= wme
->prefix
;
2397 const char *arg0
= args_string(cs
->wargs
, 0);
2399 if (*arg0
!= '\0') {
2400 data
->jumptype
= WINDOW_COPY_JUMPTOFORWARD
;
2401 free(data
->jumpchar
);
2402 data
->jumpchar
= utf8_fromcstr(arg0
);
2403 for (; np
!= 0; np
--)
2404 window_copy_cursor_jump_to(wme
);
2406 return (WINDOW_COPY_CMD_NOTHING
);
2409 static enum window_copy_cmd_action
2410 window_copy_cmd_jump_to_mark(struct window_copy_cmd_state
*cs
)
2412 struct window_mode_entry
*wme
= cs
->wme
;
2414 window_copy_jump_to_mark(wme
);
2415 return (WINDOW_COPY_CMD_NOTHING
);
2418 static enum window_copy_cmd_action
2419 window_copy_cmd_next_prompt(struct window_copy_cmd_state
*cs
)
2421 struct window_mode_entry
*wme
= cs
->wme
;
2423 window_copy_cursor_prompt(wme
, 1, args_has(cs
->wargs
, 'o'));
2424 return (WINDOW_COPY_CMD_NOTHING
);
2427 static enum window_copy_cmd_action
2428 window_copy_cmd_previous_prompt(struct window_copy_cmd_state
*cs
)
2430 struct window_mode_entry
*wme
= cs
->wme
;
2432 window_copy_cursor_prompt(wme
, 0, args_has(cs
->wargs
, 'o'));
2433 return (WINDOW_COPY_CMD_NOTHING
);
2436 static enum window_copy_cmd_action
2437 window_copy_cmd_search_backward(struct window_copy_cmd_state
*cs
)
2439 struct window_mode_entry
*wme
= cs
->wme
;
2440 struct window_copy_mode_data
*data
= wme
->data
;
2441 u_int np
= wme
->prefix
;
2443 if (!window_copy_expand_search_string(cs
))
2444 return (WINDOW_COPY_CMD_NOTHING
);
2446 if (data
->searchstr
!= NULL
) {
2447 data
->searchtype
= WINDOW_COPY_SEARCHUP
;
2448 data
->searchregex
= 1;
2450 for (; np
!= 0; np
--)
2451 window_copy_search_up(wme
, 1);
2453 return (WINDOW_COPY_CMD_NOTHING
);
2456 static enum window_copy_cmd_action
2457 window_copy_cmd_search_backward_text(struct window_copy_cmd_state
*cs
)
2459 struct window_mode_entry
*wme
= cs
->wme
;
2460 struct window_copy_mode_data
*data
= wme
->data
;
2461 u_int np
= wme
->prefix
;
2463 if (!window_copy_expand_search_string(cs
))
2464 return (WINDOW_COPY_CMD_NOTHING
);
2466 if (data
->searchstr
!= NULL
) {
2467 data
->searchtype
= WINDOW_COPY_SEARCHUP
;
2468 data
->searchregex
= 0;
2470 for (; np
!= 0; np
--)
2471 window_copy_search_up(wme
, 0);
2473 return (WINDOW_COPY_CMD_NOTHING
);
2476 static enum window_copy_cmd_action
2477 window_copy_cmd_search_forward(struct window_copy_cmd_state
*cs
)
2479 struct window_mode_entry
*wme
= cs
->wme
;
2480 struct window_copy_mode_data
*data
= wme
->data
;
2481 u_int np
= wme
->prefix
;
2483 if (!window_copy_expand_search_string(cs
))
2484 return (WINDOW_COPY_CMD_NOTHING
);
2486 if (data
->searchstr
!= NULL
) {
2487 data
->searchtype
= WINDOW_COPY_SEARCHDOWN
;
2488 data
->searchregex
= 1;
2490 for (; np
!= 0; np
--)
2491 window_copy_search_down(wme
, 1);
2493 return (WINDOW_COPY_CMD_NOTHING
);
2496 static enum window_copy_cmd_action
2497 window_copy_cmd_search_forward_text(struct window_copy_cmd_state
*cs
)
2499 struct window_mode_entry
*wme
= cs
->wme
;
2500 struct window_copy_mode_data
*data
= wme
->data
;
2501 u_int np
= wme
->prefix
;
2503 if (!window_copy_expand_search_string(cs
))
2504 return (WINDOW_COPY_CMD_NOTHING
);
2506 if (data
->searchstr
!= NULL
) {
2507 data
->searchtype
= WINDOW_COPY_SEARCHDOWN
;
2508 data
->searchregex
= 0;
2510 for (; np
!= 0; np
--)
2511 window_copy_search_down(wme
, 0);
2513 return (WINDOW_COPY_CMD_NOTHING
);
2516 static enum window_copy_cmd_action
2517 window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state
*cs
)
2519 struct window_mode_entry
*wme
= cs
->wme
;
2520 struct window_copy_mode_data
*data
= wme
->data
;
2521 const char *arg0
= args_string(cs
->wargs
, 0);
2522 const char *ss
= data
->searchstr
;
2524 enum window_copy_cmd_action action
= WINDOW_COPY_CMD_NOTHING
;
2528 log_debug("%s: %s", __func__
, arg0
);
2531 if (data
->searchx
== -1 || data
->searchy
== -1) {
2532 data
->searchx
= data
->cx
;
2533 data
->searchy
= data
->cy
;
2534 data
->searcho
= data
->oy
;
2535 } else if (ss
!= NULL
&& strcmp(arg0
, ss
) != 0) {
2536 data
->cx
= data
->searchx
;
2537 data
->cy
= data
->searchy
;
2538 data
->oy
= data
->searcho
;
2539 action
= WINDOW_COPY_CMD_REDRAW
;
2541 if (*arg0
== '\0') {
2542 window_copy_clear_marks(wme
);
2543 return (WINDOW_COPY_CMD_REDRAW
);
2548 data
->searchtype
= WINDOW_COPY_SEARCHUP
;
2549 data
->searchregex
= 0;
2550 free(data
->searchstr
);
2551 data
->searchstr
= xstrdup(arg0
);
2552 if (!window_copy_search_up(wme
, 0)) {
2553 window_copy_clear_marks(wme
);
2554 return (WINDOW_COPY_CMD_REDRAW
);
2558 data
->searchtype
= WINDOW_COPY_SEARCHDOWN
;
2559 data
->searchregex
= 0;
2560 free(data
->searchstr
);
2561 data
->searchstr
= xstrdup(arg0
);
2562 if (!window_copy_search_down(wme
, 0)) {
2563 window_copy_clear_marks(wme
);
2564 return (WINDOW_COPY_CMD_REDRAW
);
2571 static enum window_copy_cmd_action
2572 window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state
*cs
)
2574 struct window_mode_entry
*wme
= cs
->wme
;
2575 struct window_copy_mode_data
*data
= wme
->data
;
2576 const char *arg0
= args_string(cs
->wargs
, 0);
2577 const char *ss
= data
->searchstr
;
2579 enum window_copy_cmd_action action
= WINDOW_COPY_CMD_NOTHING
;
2583 log_debug("%s: %s", __func__
, arg0
);
2586 if (data
->searchx
== -1 || data
->searchy
== -1) {
2587 data
->searchx
= data
->cx
;
2588 data
->searchy
= data
->cy
;
2589 data
->searcho
= data
->oy
;
2590 } else if (ss
!= NULL
&& strcmp(arg0
, ss
) != 0) {
2591 data
->cx
= data
->searchx
;
2592 data
->cy
= data
->searchy
;
2593 data
->oy
= data
->searcho
;
2594 action
= WINDOW_COPY_CMD_REDRAW
;
2596 if (*arg0
== '\0') {
2597 window_copy_clear_marks(wme
);
2598 return (WINDOW_COPY_CMD_REDRAW
);
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
);
2613 data
->searchtype
= WINDOW_COPY_SEARCHUP
;
2614 data
->searchregex
= 0;
2615 free(data
->searchstr
);
2616 data
->searchstr
= xstrdup(arg0
);
2617 if (!window_copy_search_up(wme
, 0)) {
2618 window_copy_clear_marks(wme
);
2619 return (WINDOW_COPY_CMD_REDRAW
);
2625 static enum window_copy_cmd_action
2626 window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state
*cs
)
2628 struct window_mode_entry
*wme
= cs
->wme
;
2629 struct window_pane
*wp
= wme
->swp
;
2630 struct window_copy_mode_data
*data
= wme
->data
;
2633 return (WINDOW_COPY_CMD_NOTHING
);
2635 screen_free(data
->backing
);
2636 free(data
->backing
);
2637 data
->backing
= window_copy_clone_screen(&wp
->base
, &data
->screen
, NULL
,
2638 NULL
, wme
->swp
!= wme
->wp
);
2640 window_copy_size_changed(wme
);
2641 return (WINDOW_COPY_CMD_REDRAW
);
2644 static const struct {
2645 const char *command
;
2648 struct args_parse args
;
2649 enum window_copy_cmd_clear clear
;
2650 enum window_copy_cmd_action (*f
)(struct window_copy_cmd_state
*);
2651 } window_copy_cmd_table
[] = {
2652 { .command
= "append-selection",
2653 .args
= { "", 0, 0, NULL
},
2654 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2655 .f
= window_copy_cmd_append_selection
2657 { .command
= "append-selection-and-cancel",
2658 .args
= { "", 0, 0, NULL
},
2659 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2660 .f
= window_copy_cmd_append_selection_and_cancel
2662 { .command
= "back-to-indentation",
2663 .args
= { "", 0, 0, NULL
},
2664 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2665 .f
= window_copy_cmd_back_to_indentation
2667 { .command
= "begin-selection",
2668 .args
= { "", 0, 0, NULL
},
2669 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2670 .f
= window_copy_cmd_begin_selection
2672 { .command
= "bottom-line",
2673 .args
= { "", 0, 0, NULL
},
2674 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2675 .f
= window_copy_cmd_bottom_line
2677 { .command
= "cancel",
2678 .args
= { "", 0, 0, NULL
},
2679 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2680 .f
= window_copy_cmd_cancel
2682 { .command
= "clear-selection",
2683 .args
= { "", 0, 0, NULL
},
2684 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2685 .f
= window_copy_cmd_clear_selection
2687 { .command
= "copy-end-of-line",
2688 .args
= { "CP", 0, 1, NULL
},
2689 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2690 .f
= window_copy_cmd_copy_end_of_line
2692 { .command
= "copy-end-of-line-and-cancel",
2693 .args
= { "CP", 0, 1, NULL
},
2694 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2695 .f
= window_copy_cmd_copy_end_of_line_and_cancel
2697 { .command
= "copy-pipe-end-of-line",
2698 .args
= { "CP", 0, 2, NULL
},
2699 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2700 .f
= window_copy_cmd_copy_pipe_end_of_line
2702 { .command
= "copy-pipe-end-of-line-and-cancel",
2703 .args
= { "CP", 0, 2, NULL
},
2704 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2705 .f
= window_copy_cmd_copy_pipe_end_of_line_and_cancel
2707 { .command
= "copy-line",
2708 .args
= { "CP", 0, 1, NULL
},
2709 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2710 .f
= window_copy_cmd_copy_line
2712 { .command
= "copy-line-and-cancel",
2713 .args
= { "CP", 0, 1, NULL
},
2714 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2715 .f
= window_copy_cmd_copy_line_and_cancel
2717 { .command
= "copy-pipe-line",
2718 .args
= { "CP", 0, 2, NULL
},
2719 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2720 .f
= window_copy_cmd_copy_pipe_line
2722 { .command
= "copy-pipe-line-and-cancel",
2723 .args
= { "CP", 0, 2, NULL
},
2724 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2725 .f
= window_copy_cmd_copy_pipe_line_and_cancel
2727 { .command
= "copy-pipe-no-clear",
2728 .args
= { "CP", 0, 2, NULL
},
2729 .clear
= WINDOW_COPY_CMD_CLEAR_NEVER
,
2730 .f
= window_copy_cmd_copy_pipe_no_clear
2732 { .command
= "copy-pipe",
2733 .args
= { "CP", 0, 2, NULL
},
2734 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2735 .f
= window_copy_cmd_copy_pipe
2737 { .command
= "copy-pipe-and-cancel",
2738 .args
= { "CP", 0, 2, NULL
},
2739 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2740 .f
= window_copy_cmd_copy_pipe_and_cancel
2742 { .command
= "copy-selection-no-clear",
2743 .args
= { "CP", 0, 1, NULL
},
2744 .clear
= WINDOW_COPY_CMD_CLEAR_NEVER
,
2745 .f
= window_copy_cmd_copy_selection_no_clear
2747 { .command
= "copy-selection",
2748 .args
= { "CP", 0, 1, NULL
},
2749 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2750 .f
= window_copy_cmd_copy_selection
2752 { .command
= "copy-selection-and-cancel",
2753 .args
= { "CP", 0, 1, NULL
},
2754 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2755 .f
= window_copy_cmd_copy_selection_and_cancel
2757 { .command
= "cursor-down",
2758 .args
= { "", 0, 0, NULL
},
2759 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2760 .f
= window_copy_cmd_cursor_down
2762 { .command
= "cursor-down-and-cancel",
2763 .args
= { "", 0, 0, NULL
},
2764 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2765 .f
= window_copy_cmd_cursor_down_and_cancel
2767 { .command
= "cursor-left",
2768 .args
= { "", 0, 0, NULL
},
2769 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2770 .f
= window_copy_cmd_cursor_left
2772 { .command
= "cursor-right",
2773 .args
= { "", 0, 0, NULL
},
2774 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2775 .f
= window_copy_cmd_cursor_right
2777 { .command
= "cursor-up",
2778 .args
= { "", 0, 0, NULL
},
2779 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2780 .f
= window_copy_cmd_cursor_up
2782 { .command
= "end-of-line",
2783 .args
= { "", 0, 0, NULL
},
2784 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2785 .f
= window_copy_cmd_end_of_line
2787 { .command
= "goto-line",
2788 .args
= { "", 1, 1, NULL
},
2789 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2790 .f
= window_copy_cmd_goto_line
2792 { .command
= "halfpage-down",
2793 .args
= { "", 0, 0, NULL
},
2794 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2795 .f
= window_copy_cmd_halfpage_down
2797 { .command
= "halfpage-down-and-cancel",
2798 .args
= { "", 0, 0, NULL
},
2799 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2800 .f
= window_copy_cmd_halfpage_down_and_cancel
2802 { .command
= "halfpage-up",
2803 .args
= { "", 0, 0, NULL
},
2804 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2805 .f
= window_copy_cmd_halfpage_up
2807 { .command
= "history-bottom",
2808 .args
= { "", 0, 0, NULL
},
2809 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2810 .f
= window_copy_cmd_history_bottom
2812 { .command
= "history-top",
2813 .args
= { "", 0, 0, NULL
},
2814 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2815 .f
= window_copy_cmd_history_top
2817 { .command
= "jump-again",
2818 .args
= { "", 0, 0, NULL
},
2819 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2820 .f
= window_copy_cmd_jump_again
2822 { .command
= "jump-backward",
2823 .args
= { "", 1, 1, NULL
},
2824 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2825 .f
= window_copy_cmd_jump_backward
2827 { .command
= "jump-forward",
2828 .args
= { "", 1, 1, NULL
},
2829 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2830 .f
= window_copy_cmd_jump_forward
2832 { .command
= "jump-reverse",
2833 .args
= { "", 0, 0, NULL
},
2834 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2835 .f
= window_copy_cmd_jump_reverse
2837 { .command
= "jump-to-backward",
2838 .args
= { "", 1, 1, NULL
},
2839 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2840 .f
= window_copy_cmd_jump_to_backward
2842 { .command
= "jump-to-forward",
2843 .args
= { "", 1, 1, NULL
},
2844 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2845 .f
= window_copy_cmd_jump_to_forward
2847 { .command
= "jump-to-mark",
2848 .args
= { "", 0, 0, NULL
},
2849 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2850 .f
= window_copy_cmd_jump_to_mark
2852 { .command
= "next-prompt",
2853 .args
= { "o", 0, 0, NULL
},
2854 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2855 .f
= window_copy_cmd_next_prompt
2857 { .command
= "previous-prompt",
2858 .args
= { "o", 0, 0, NULL
},
2859 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2860 .f
= window_copy_cmd_previous_prompt
2862 { .command
= "middle-line",
2863 .args
= { "", 0, 0, NULL
},
2864 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2865 .f
= window_copy_cmd_middle_line
2867 { .command
= "next-matching-bracket",
2868 .args
= { "", 0, 0, NULL
},
2869 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2870 .f
= window_copy_cmd_next_matching_bracket
2872 { .command
= "next-paragraph",
2873 .args
= { "", 0, 0, NULL
},
2874 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2875 .f
= window_copy_cmd_next_paragraph
2877 { .command
= "next-space",
2878 .args
= { "", 0, 0, NULL
},
2879 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2880 .f
= window_copy_cmd_next_space
2882 { .command
= "next-space-end",
2883 .args
= { "", 0, 0, NULL
},
2884 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2885 .f
= window_copy_cmd_next_space_end
2887 { .command
= "next-word",
2888 .args
= { "", 0, 0, NULL
},
2889 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2890 .f
= window_copy_cmd_next_word
2892 { .command
= "next-word-end",
2893 .args
= { "", 0, 0, NULL
},
2894 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2895 .f
= window_copy_cmd_next_word_end
2897 { .command
= "other-end",
2898 .args
= { "", 0, 0, NULL
},
2899 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2900 .f
= window_copy_cmd_other_end
2902 { .command
= "page-down",
2903 .args
= { "", 0, 0, NULL
},
2904 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2905 .f
= window_copy_cmd_page_down
2907 { .command
= "page-down-and-cancel",
2908 .args
= { "", 0, 0, NULL
},
2909 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2910 .f
= window_copy_cmd_page_down_and_cancel
2912 { .command
= "page-up",
2913 .args
= { "", 0, 0, NULL
},
2914 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2915 .f
= window_copy_cmd_page_up
2917 { .command
= "pipe-no-clear",
2918 .args
= { "", 0, 1, NULL
},
2919 .clear
= WINDOW_COPY_CMD_CLEAR_NEVER
,
2920 .f
= window_copy_cmd_pipe_no_clear
2922 { .command
= "pipe",
2923 .args
= { "", 0, 1, NULL
},
2924 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2925 .f
= window_copy_cmd_pipe
2927 { .command
= "pipe-and-cancel",
2928 .args
= { "", 0, 1, NULL
},
2929 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2930 .f
= window_copy_cmd_pipe_and_cancel
2932 { .command
= "previous-matching-bracket",
2933 .args
= { "", 0, 0, NULL
},
2934 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2935 .f
= window_copy_cmd_previous_matching_bracket
2937 { .command
= "previous-paragraph",
2938 .args
= { "", 0, 0, NULL
},
2939 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2940 .f
= window_copy_cmd_previous_paragraph
2942 { .command
= "previous-space",
2943 .args
= { "", 0, 0, NULL
},
2944 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2945 .f
= window_copy_cmd_previous_space
2947 { .command
= "previous-word",
2948 .args
= { "", 0, 0, NULL
},
2949 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2950 .f
= window_copy_cmd_previous_word
2952 { .command
= "rectangle-on",
2953 .args
= { "", 0, 0, NULL
},
2954 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2955 .f
= window_copy_cmd_rectangle_on
2957 { .command
= "rectangle-off",
2958 .args
= { "", 0, 0, NULL
},
2959 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2960 .f
= window_copy_cmd_rectangle_off
2962 { .command
= "rectangle-toggle",
2963 .args
= { "", 0, 0, NULL
},
2964 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2965 .f
= window_copy_cmd_rectangle_toggle
2967 { .command
= "refresh-from-pane",
2968 .args
= { "", 0, 0, NULL
},
2969 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2970 .f
= window_copy_cmd_refresh_from_pane
2972 { .command
= "scroll-bottom",
2973 .args
= { "", 0, 0, NULL
},
2974 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2975 .f
= window_copy_cmd_scroll_bottom
2977 { .command
= "scroll-down",
2978 .args
= { "", 0, 0, NULL
},
2979 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
2980 .f
= window_copy_cmd_scroll_down
2982 { .command
= "scroll-down-and-cancel",
2983 .args
= { "", 0, 0, NULL
},
2984 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2985 .f
= window_copy_cmd_scroll_down_and_cancel
2987 { .command
= "scroll-middle",
2988 .args
= { "", 0, 0, NULL
},
2989 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2990 .f
= window_copy_cmd_scroll_middle
2992 { .command
= "scroll-top",
2993 .args
= { "", 0, 0, NULL
},
2994 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
2995 .f
= window_copy_cmd_scroll_top
2997 { .command
= "scroll-up",
2998 .args
= { "", 0, 0, NULL
},
2999 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
3000 .f
= window_copy_cmd_scroll_up
3002 { .command
= "search-again",
3003 .args
= { "", 0, 0, NULL
},
3004 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3005 .f
= window_copy_cmd_search_again
3007 { .command
= "search-backward",
3008 .args
= { "", 0, 1, NULL
},
3009 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3010 .f
= window_copy_cmd_search_backward
3012 { .command
= "search-backward-text",
3013 .args
= { "", 0, 1, NULL
},
3014 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3015 .f
= window_copy_cmd_search_backward_text
3017 { .command
= "search-backward-incremental",
3018 .args
= { "", 1, 1, NULL
},
3019 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3020 .f
= window_copy_cmd_search_backward_incremental
3022 { .command
= "search-forward",
3023 .args
= { "", 0, 1, NULL
},
3024 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3025 .f
= window_copy_cmd_search_forward
3027 { .command
= "search-forward-text",
3028 .args
= { "", 0, 1, NULL
},
3029 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3030 .f
= window_copy_cmd_search_forward_text
3032 { .command
= "search-forward-incremental",
3033 .args
= { "", 1, 1, NULL
},
3034 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3035 .f
= window_copy_cmd_search_forward_incremental
3037 { .command
= "search-reverse",
3038 .args
= { "", 0, 0, NULL
},
3039 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3040 .f
= window_copy_cmd_search_reverse
3042 { .command
= "select-line",
3043 .args
= { "", 0, 0, NULL
},
3044 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3045 .f
= window_copy_cmd_select_line
3047 { .command
= "select-word",
3048 .args
= { "", 0, 0, NULL
},
3049 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3050 .f
= window_copy_cmd_select_word
3052 { .command
= "set-mark",
3053 .args
= { "", 0, 0, NULL
},
3054 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3055 .f
= window_copy_cmd_set_mark
3057 { .command
= "start-of-line",
3058 .args
= { "", 0, 0, NULL
},
3059 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
3060 .f
= window_copy_cmd_start_of_line
3062 { .command
= "stop-selection",
3063 .args
= { "", 0, 0, NULL
},
3064 .clear
= WINDOW_COPY_CMD_CLEAR_ALWAYS
,
3065 .f
= window_copy_cmd_stop_selection
3067 { .command
= "toggle-position",
3068 .args
= { "", 0, 0, NULL
},
3069 .clear
= WINDOW_COPY_CMD_CLEAR_NEVER
,
3070 .f
= window_copy_cmd_toggle_position
3072 { .command
= "top-line",
3073 .args
= { "", 0, 0, NULL
},
3074 .clear
= WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
,
3075 .f
= window_copy_cmd_top_line
3080 window_copy_command(struct window_mode_entry
*wme
, struct client
*c
,
3081 struct session
*s
, struct winlink
*wl
, struct args
*args
,
3082 struct mouse_event
*m
)
3084 struct window_copy_mode_data
*data
= wme
->data
;
3085 struct window_pane
*wp
= wme
->wp
;
3086 struct window_copy_cmd_state cs
;
3087 enum window_copy_cmd_action action
;
3088 enum window_copy_cmd_clear clear
= WINDOW_COPY_CMD_CLEAR_NEVER
;
3089 const char *command
;
3090 u_int i
, count
= args_count(args
);
3096 command
= args_string(args
, 0);
3098 if (m
!= NULL
&& m
->valid
&& !MOUSE_WHEEL(m
->b
))
3099 window_copy_move_mouse(m
);
3110 action
= WINDOW_COPY_CMD_NOTHING
;
3111 for (i
= 0; i
< nitems(window_copy_cmd_table
); i
++) {
3112 if (strcmp(window_copy_cmd_table
[i
].command
, command
) == 0) {
3113 cs
.wargs
= args_parse(&window_copy_cmd_table
[i
].args
,
3114 args_values(args
), count
, &error
);
3116 if (error
!= NULL
) {
3120 if (cs
.wargs
== NULL
)
3123 clear
= window_copy_cmd_table
[i
].clear
;
3124 action
= window_copy_cmd_table
[i
].f(&cs
);
3125 args_free(cs
.wargs
);
3131 if (strncmp(command
, "search-", 7) != 0 && data
->searchmark
!= NULL
) {
3132 keys
= options_get_number(wp
->window
->options
, "mode-keys");
3133 if (clear
== WINDOW_COPY_CMD_CLEAR_EMACS_ONLY
&&
3135 clear
= WINDOW_COPY_CMD_CLEAR_NEVER
;
3136 if (clear
!= WINDOW_COPY_CMD_CLEAR_NEVER
) {
3137 window_copy_clear_marks(wme
);
3138 data
->searchx
= data
->searchy
= -1;
3140 if (action
== WINDOW_COPY_CMD_NOTHING
)
3141 action
= WINDOW_COPY_CMD_REDRAW
;
3145 if (action
== WINDOW_COPY_CMD_CANCEL
)
3146 window_pane_reset_mode(wp
);
3147 else if (action
== WINDOW_COPY_CMD_REDRAW
)
3148 window_copy_redraw_screen(wme
);
3152 window_copy_scroll_to(struct window_mode_entry
*wme
, u_int px
, u_int py
,
3155 struct window_copy_mode_data
*data
= wme
->data
;
3156 struct grid
*gd
= data
->backing
->grid
;
3161 if (py
>= gd
->hsize
- data
->oy
&& py
< gd
->hsize
- data
->oy
+ gd
->sy
)
3162 data
->cy
= py
- (gd
->hsize
- data
->oy
);
3168 } else if (py
> gd
->hsize
+ gd
->sy
- gap
) {
3170 data
->cy
= py
- gd
->hsize
;
3172 offset
= py
+ gap
- gd
->sy
;
3173 data
->cy
= py
- offset
;
3175 data
->oy
= gd
->hsize
- offset
;
3178 if (!no_redraw
&& data
->searchmark
!= NULL
&& !data
->timeout
)
3179 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
3180 window_copy_update_selection(wme
, 1, 0);
3182 window_copy_redraw_screen(wme
);
3186 window_copy_search_compare(struct grid
*gd
, u_int px
, u_int py
,
3187 struct grid
*sgd
, u_int spx
, int cis
)
3189 struct grid_cell gc
, sgc
;
3190 const struct utf8_data
*ud
, *sud
;
3192 grid_get_cell(gd
, px
, py
, &gc
);
3194 grid_get_cell(sgd
, spx
, 0, &sgc
);
3197 if (*sud
->data
== '\t' && sud
->size
== 1 && gc
.flags
& GRID_FLAG_TAB
)
3200 if (ud
->size
!= sud
->size
|| ud
->width
!= sud
->width
)
3203 if (cis
&& ud
->size
== 1)
3204 return (tolower(ud
->data
[0]) == sud
->data
[0]);
3206 return (memcmp(ud
->data
, sud
->data
, ud
->size
) == 0);
3210 window_copy_search_lr(struct grid
*gd
, struct grid
*sgd
, u_int
*ppx
, u_int py
,
3211 u_int first
, u_int last
, int cis
)
3213 u_int ax
, bx
, px
, pywrap
, endline
, padding
;
3215 struct grid_line
*gl
;
3216 struct grid_cell gc
;
3218 endline
= gd
->hsize
+ gd
->sy
- 1;
3219 for (ax
= first
; ax
< last
; ax
++) {
3221 for (bx
= 0; bx
< sgd
->sx
; bx
++) {
3222 px
= ax
+ bx
+ padding
;
3225 while (px
>= gd
->sx
&& pywrap
< endline
) {
3226 gl
= grid_get_line(gd
, pywrap
);
3227 if (~gl
->flags
& GRID_LINE_WRAPPED
)
3232 /* We have run off the end of the grid. */
3233 if (px
- padding
>= gd
->sx
)
3236 grid_get_cell(gd
, px
, pywrap
, &gc
);
3237 if (gc
.flags
& GRID_FLAG_TAB
)
3238 padding
+= gc
.data
.width
- 1;
3240 matched
= window_copy_search_compare(gd
, px
, pywrap
,
3245 if (bx
== sgd
->sx
) {
3254 window_copy_search_rl(struct grid
*gd
,
3255 struct grid
*sgd
, u_int
*ppx
, u_int py
, u_int first
, u_int last
, int cis
)
3257 u_int ax
, bx
, px
, pywrap
, endline
, padding
;
3259 struct grid_line
*gl
;
3260 struct grid_cell gc
;
3262 endline
= gd
->hsize
+ gd
->sy
- 1;
3263 for (ax
= last
; ax
> first
; ax
--) {
3265 for (bx
= 0; bx
< sgd
->sx
; bx
++) {
3266 px
= ax
- 1 + bx
+ padding
;
3269 while (px
>= gd
->sx
&& pywrap
< endline
) {
3270 gl
= grid_get_line(gd
, pywrap
);
3271 if (~gl
->flags
& GRID_LINE_WRAPPED
)
3276 /* We have run off the end of the grid. */
3277 if (px
- padding
>= gd
->sx
)
3280 grid_get_cell(gd
, px
, pywrap
, &gc
);
3281 if (gc
.flags
& GRID_FLAG_TAB
)
3282 padding
+= gc
.data
.width
- 1;
3284 matched
= window_copy_search_compare(gd
, px
, pywrap
,
3289 if (bx
== sgd
->sx
) {
3298 window_copy_search_lr_regex(struct grid
*gd
, u_int
*ppx
, u_int
*psx
, u_int py
,
3299 u_int first
, u_int last
, regex_t
*reg
)
3302 u_int endline
, foundx
, foundy
, len
, pywrap
, size
= 1;
3304 regmatch_t regmatch
;
3305 struct grid_line
*gl
;
3308 * This can happen during search if the last match was the last
3309 * character on a line.
3314 /* Set flags for regex search. */
3316 eflags
|= REG_NOTBOL
;
3318 /* Need to look at the entire string. */
3319 buf
= xmalloc(size
);
3321 buf
= window_copy_stringify(gd
, py
, first
, gd
->sx
, buf
, &size
);
3322 len
= gd
->sx
- first
;
3323 endline
= gd
->hsize
+ gd
->sy
- 1;
3325 while (buf
!= NULL
&&
3326 pywrap
<= endline
&&
3327 len
< WINDOW_COPY_SEARCH_MAX_LINE
) {
3328 gl
= grid_get_line(gd
, pywrap
);
3329 if (~gl
->flags
& GRID_LINE_WRAPPED
)
3332 buf
= window_copy_stringify(gd
, pywrap
, 0, gd
->sx
, buf
, &size
);
3336 if (regexec(reg
, buf
, 1, ®match
, eflags
) == 0 &&
3337 regmatch
.rm_so
!= regmatch
.rm_eo
) {
3340 window_copy_cstrtocellpos(gd
, len
, &foundx
, &foundy
,
3341 buf
+ regmatch
.rm_so
);
3342 if (foundy
== py
&& foundx
< last
) {
3344 len
-= foundx
- first
;
3345 window_copy_cstrtocellpos(gd
, len
, &foundx
, &foundy
,
3346 buf
+ regmatch
.rm_eo
);
3348 while (foundy
> py
) {
3365 window_copy_search_rl_regex(struct grid
*gd
, u_int
*ppx
, u_int
*psx
, u_int py
,
3366 u_int first
, u_int last
, regex_t
*reg
)
3369 u_int endline
, len
, pywrap
, size
= 1;
3371 struct grid_line
*gl
;
3373 /* Set flags for regex search. */
3375 eflags
|= REG_NOTBOL
;
3377 /* Need to look at the entire string. */
3378 buf
= xmalloc(size
);
3380 buf
= window_copy_stringify(gd
, py
, first
, gd
->sx
, buf
, &size
);
3381 len
= gd
->sx
- first
;
3382 endline
= gd
->hsize
+ gd
->sy
- 1;
3384 while (buf
!= NULL
&&
3385 pywrap
<= endline
&&
3386 len
< WINDOW_COPY_SEARCH_MAX_LINE
) {
3387 gl
= grid_get_line(gd
, pywrap
);
3388 if (~gl
->flags
& GRID_LINE_WRAPPED
)
3391 buf
= window_copy_stringify(gd
, pywrap
, 0, gd
->sx
, buf
, &size
);
3395 if (window_copy_last_regex(gd
, py
, first
, last
, len
, ppx
, psx
, buf
,
3409 window_copy_cellstring(const struct grid_line
*gl
, u_int px
, size_t *size
,
3412 static struct utf8_data ud
;
3413 struct grid_cell_entry
*gce
;
3416 if (px
>= gl
->cellsize
) {
3422 gce
= &gl
->celldata
[px
];
3423 if (gce
->flags
& GRID_FLAG_PADDING
) {
3428 if (~gce
->flags
& GRID_FLAG_EXTENDED
) {
3431 return (&gce
->data
.data
);
3433 if (gce
->flags
& GRID_FLAG_TAB
) {
3439 utf8_to_data(gl
->extddata
[gce
->offset
].data
, &ud
);
3448 copy
= xmalloc(ud
.size
);
3449 memcpy(copy
, ud
.data
, ud
.size
);
3453 /* Find last match in given range. */
3455 window_copy_last_regex(struct grid
*gd
, u_int py
, u_int first
, u_int last
,
3456 u_int len
, u_int
*ppx
, u_int
*psx
, const char *buf
, const regex_t
*preg
,
3459 u_int foundx
, foundy
, oldx
, px
= 0, savepx
, savesx
= 0;
3460 regmatch_t regmatch
;
3465 while (regexec(preg
, buf
+ px
, 1, ®match
, eflags
) == 0) {
3466 if (regmatch
.rm_so
== regmatch
.rm_eo
)
3468 window_copy_cstrtocellpos(gd
, len
, &foundx
, &foundy
,
3469 buf
+ px
+ regmatch
.rm_so
);
3470 if (foundy
> py
|| foundx
>= last
)
3472 len
-= foundx
- oldx
;
3474 window_copy_cstrtocellpos(gd
, len
, &foundx
, &foundy
,
3475 buf
+ px
+ regmatch
.rm_eo
);
3476 if (foundy
> py
|| foundx
>= last
) {
3479 while (foundy
> py
) {
3486 savesx
= foundx
- savepx
;
3490 px
+= regmatch
.rm_eo
;
3504 /* Stringify line and append to input buffer. Caller frees. */
3506 window_copy_stringify(struct grid
*gd
, u_int py
, u_int first
, u_int last
,
3507 char *buf
, u_int
*size
)
3509 u_int ax
, bx
, newsize
= *size
;
3510 const struct grid_line
*gl
;
3512 size_t bufsize
= 1024, dlen
;
3515 while (bufsize
< newsize
)
3517 buf
= xrealloc(buf
, bufsize
);
3519 gl
= grid_peek_line(gd
, py
);
3521 for (ax
= first
; ax
< last
; ax
++) {
3522 d
= window_copy_cellstring(gl
, ax
, &dlen
, &allocated
);
3524 while (bufsize
< newsize
) {
3526 buf
= xrealloc(buf
, bufsize
);
3531 memcpy(buf
+ bx
, d
, dlen
);
3537 buf
[newsize
- 1] = '\0';
3543 /* Map start of C string containing UTF-8 data to grid cell position. */
3545 window_copy_cstrtocellpos(struct grid
*gd
, u_int ncells
, u_int
*ppx
, u_int
*ppy
,
3548 u_int cell
, ccell
, px
, pywrap
, pos
, len
;
3550 const struct grid_line
*gl
;
3559 /* Populate the array of cell data. */
3560 cells
= xreallocarray(NULL
, ncells
, sizeof cells
[0]);
3564 gl
= grid_peek_line(gd
, pywrap
);
3565 while (cell
< ncells
) {
3566 cells
[cell
].d
= window_copy_cellstring(gl
, px
,
3567 &cells
[cell
].dlen
, &cells
[cell
].allocated
);
3573 gl
= grid_peek_line(gd
, pywrap
);
3577 /* Locate starting cell. */
3580 while (cell
< ncells
) {
3584 while (ccell
< ncells
) {
3585 if (str
[pos
] == '\0') {
3590 dlen
= cells
[ccell
].dlen
;
3592 if (str
[pos
] != *d
) {
3598 if (dlen
> len
- pos
)
3600 if (memcmp(str
+ pos
, d
, dlen
) != 0) {
3613 /* If not found this will be one past the end. */
3616 while (px
>= gd
->sx
) {
3624 /* Free cell data. */
3625 for (cell
= 0; cell
< ncells
; cell
++) {
3626 if (cells
[cell
].allocated
)
3627 free((void *)cells
[cell
].d
);
3633 window_copy_move_left(struct screen
*s
, u_int
*fx
, u_int
*fy
, int wrapflag
)
3635 if (*fx
== 0) { /* left */
3636 if (*fy
== 0) { /* top */
3638 *fx
= screen_size_x(s
) - 1;
3639 *fy
= screen_hsize(s
) + screen_size_y(s
) - 1;
3643 *fx
= screen_size_x(s
) - 1;
3650 window_copy_move_right(struct screen
*s
, u_int
*fx
, u_int
*fy
, int wrapflag
)
3652 if (*fx
== screen_size_x(s
) - 1) { /* right */
3653 if (*fy
== screen_hsize(s
) + screen_size_y(s
) - 1) { /* bottom */
3667 window_copy_is_lowercase(const char *ptr
)
3669 while (*ptr
!= '\0') {
3670 if (*ptr
!= tolower((u_char
)*ptr
))
3678 * Handle backward wrapped regex searches with overlapping matches. In this case
3679 * find the longest overlapping match from previous wrapped lines.
3682 window_copy_search_back_overlap(struct grid
*gd
, regex_t
*preg
, u_int
*ppx
,
3683 u_int
*psx
, u_int
*ppy
, u_int endline
)
3685 u_int endx
, endy
, oldendx
, oldendy
, px
, py
, sx
;
3688 oldendx
= *ppx
+ *psx
;
3690 while (oldendx
> gd
->sx
- 1) {
3698 while (found
&& px
== 0 && py
- 1 > endline
&&
3699 grid_get_line(gd
, py
- 2)->flags
& GRID_LINE_WRAPPED
&&
3700 endx
== oldendx
&& endy
== oldendy
) {
3702 found
= window_copy_search_rl_regex(gd
, &px
, &sx
, py
- 1, 0,
3707 while (endx
> gd
->sx
- 1) {
3711 if (endx
== oldendx
&& endy
== oldendy
) {
3720 * Search for text stored in sgd starting from position fx,fy up to endline. If
3721 * found, jump to it. If cis then ignore case. The direction is 0 for searching
3722 * up, down otherwise. If wrap then go to begin/end of grid and try again if
3726 window_copy_search_jump(struct window_mode_entry
*wme
, struct grid
*gd
,
3727 struct grid
*sgd
, u_int fx
, u_int fy
, u_int endline
, int cis
, int wrap
,
3728 int direction
, int regex
)
3730 u_int i
, px
, sx
, ssize
= 1;
3731 int found
= 0, cflags
= REG_EXTENDED
;
3736 sbuf
= xmalloc(ssize
);
3738 sbuf
= window_copy_stringify(sgd
, 0, 0, sgd
->sx
, sbuf
, &ssize
);
3740 cflags
|= REG_ICASE
;
3741 if (regcomp(®
, sbuf
, cflags
) != 0) {
3749 for (i
= fy
; i
<= endline
; i
++) {
3751 found
= window_copy_search_lr_regex(gd
,
3752 &px
, &sx
, i
, fx
, gd
->sx
, ®
);
3754 found
= window_copy_search_lr(gd
, sgd
,
3755 &px
, i
, fx
, gd
->sx
, cis
);
3762 for (i
= fy
+ 1; endline
< i
; i
--) {
3764 found
= window_copy_search_rl_regex(gd
,
3765 &px
, &sx
, i
- 1, 0, fx
+ 1, ®
);
3767 window_copy_search_back_overlap(gd
,
3768 ®
, &px
, &sx
, &i
, endline
);
3771 found
= window_copy_search_rl(gd
, sgd
,
3772 &px
, i
- 1, 0, fx
+ 1, cis
);
3785 window_copy_scroll_to(wme
, px
, i
, 1);
3789 return (window_copy_search_jump(wme
, gd
, sgd
,
3790 direction
? 0 : gd
->sx
- 1,
3791 direction
? 0 : gd
->hsize
+ gd
->sy
- 1, fy
, cis
, 0,
3798 window_copy_move_after_search_mark(struct window_copy_mode_data
*data
,
3799 u_int
*fx
, u_int
*fy
, int wrapflag
)
3801 struct screen
*s
= data
->backing
;
3804 if (window_copy_search_mark_at(data
, *fx
, *fy
, &start
) == 0 &&
3805 data
->searchmark
[start
] != 0) {
3806 while (window_copy_search_mark_at(data
, *fx
, *fy
, &at
) == 0) {
3807 if (data
->searchmark
[at
] != data
->searchmark
[start
])
3809 /* Stop if not wrapping and at the end of the grid. */
3811 *fx
== screen_size_x(s
) - 1 &&
3812 *fy
== screen_hsize(s
) + screen_size_y(s
) - 1)
3815 window_copy_move_right(s
, fx
, fy
, wrapflag
);
3821 * Search in for text searchstr. If direction is 0 then search up, otherwise
3825 window_copy_search(struct window_mode_entry
*wme
, int direction
, int regex
)
3827 struct window_pane
*wp
= wme
->wp
;
3828 struct window_copy_mode_data
*data
= wme
->data
;
3829 struct screen
*s
= data
->backing
, ss
;
3830 struct screen_write_ctx ctx
;
3831 struct grid
*gd
= s
->grid
;
3832 const char *str
= data
->searchstr
;
3833 u_int at
, endline
, fx
, fy
, start
, ssx
;
3834 int cis
, found
, keys
, visible_only
;
3837 if (regex
&& str
[strcspn(str
, "^$*+()?[].\\")] == '\0')
3840 data
->searchdirection
= direction
;
3845 if (data
->searchall
|| wp
->searchstr
== NULL
||
3846 wp
->searchregex
!= regex
) {
3848 data
->searchall
= 0;
3850 visible_only
= (strcmp(wp
->searchstr
, str
) == 0);
3851 if (visible_only
== 0 && data
->searchmark
!= NULL
)
3852 window_copy_clear_marks(wme
);
3853 free(wp
->searchstr
);
3854 wp
->searchstr
= xstrdup(str
);
3855 wp
->searchregex
= regex
;
3858 fy
= screen_hsize(data
->backing
) - data
->oy
+ data
->cy
;
3860 if ((ssx
= screen_write_strlen("%s", str
)) == 0)
3862 screen_init(&ss
, ssx
, 1, 0);
3863 screen_write_start(&ctx
, &ss
);
3864 screen_write_nputs(&ctx
, -1, &grid_default_cell
, "%s", str
);
3865 screen_write_stop(&ctx
);
3867 wrapflag
= options_get_number(wp
->window
->options
, "wrap-search");
3868 cis
= window_copy_is_lowercase(str
);
3870 keys
= options_get_number(wp
->window
->options
, "mode-keys");
3874 * Behave according to mode-keys. If it is emacs, search forward
3875 * leaves the cursor after the match. If it is vi, the cursor
3876 * remains at the beginning of the match, regardless of
3877 * direction, which means that we need to start the next search
3878 * after the term the cursor is currently on when searching
3881 if (keys
== MODEKEY_VI
) {
3882 if (data
->searchmark
!= NULL
)
3883 window_copy_move_after_search_mark(data
, &fx
,
3887 * When there are no search marks, start the
3888 * search after the current cursor position.
3890 window_copy_move_right(s
, &fx
, &fy
, wrapflag
);
3893 endline
= gd
->hsize
+ gd
->sy
- 1;
3895 window_copy_move_left(s
, &fx
, &fy
, wrapflag
);
3899 found
= window_copy_search_jump(wme
, gd
, ss
.grid
, fx
, fy
, endline
, cis
,
3900 wrapflag
, direction
, regex
);
3902 window_copy_search_marks(wme
, &ss
, regex
, visible_only
);
3904 fy
= screen_hsize(data
->backing
) - data
->oy
+ data
->cy
;
3907 * When searching forward, if the cursor is not at the beginning
3908 * of the mark, search again.
3911 window_copy_search_mark_at(data
, fx
, fy
, &at
) == 0 &&
3913 data
->searchmark
!= NULL
&&
3914 data
->searchmark
[at
] == data
->searchmark
[at
- 1]) {
3915 window_copy_move_after_search_mark(data
, &fx
, &fy
,
3917 window_copy_search_jump(wme
, gd
, ss
.grid
, fx
,
3918 fy
, endline
, cis
, wrapflag
, direction
,
3921 fy
= screen_hsize(data
->backing
) - data
->oy
+ data
->cy
;
3926 * When in Emacs mode, position the cursor just after
3929 if (keys
== MODEKEY_EMACS
) {
3930 window_copy_move_after_search_mark(data
, &fx
,
3933 data
->cy
= fy
- screen_hsize(data
->backing
) +
3938 * When searching backward, position the cursor at the
3939 * beginning of the mark.
3941 if (window_copy_search_mark_at(data
, fx
, fy
,
3943 while (window_copy_search_mark_at(data
, fx
, fy
,
3945 data
->searchmark
!= NULL
&&
3946 data
->searchmark
[at
] ==
3947 data
->searchmark
[start
]) {
3950 screen_hsize(data
->backing
) +
3955 window_copy_move_left(s
, &fx
, &fy
, 0);
3960 window_copy_redraw_screen(wme
);
3967 window_copy_visible_lines(struct window_copy_mode_data
*data
, u_int
*start
,
3970 struct grid
*gd
= data
->backing
->grid
;
3971 const struct grid_line
*gl
;
3973 for (*start
= gd
->hsize
- data
->oy
; *start
> 0; (*start
)--) {
3974 gl
= grid_peek_line(gd
, (*start
) - 1);
3975 if (~gl
->flags
& GRID_LINE_WRAPPED
)
3978 *end
= gd
->hsize
- data
->oy
+ gd
->sy
;
3982 window_copy_search_mark_at(struct window_copy_mode_data
*data
, u_int px
,
3983 u_int py
, u_int
*at
)
3985 struct screen
*s
= data
->backing
;
3986 struct grid
*gd
= s
->grid
;
3988 if (py
< gd
->hsize
- data
->oy
)
3990 if (py
> gd
->hsize
- data
->oy
+ gd
->sy
- 1)
3992 *at
= ((py
- (gd
->hsize
- data
->oy
)) * gd
->sx
) + px
;
3997 window_copy_clip_width(u_int width
, u_int b
, u_int sx
, u_int sy
)
3999 return ((b
+ width
> sx
* sy
) ? (sx
* sy
) - b
: width
);
4003 window_copy_search_mark_match(struct window_copy_mode_data
*data
, u_int px
,
4004 u_int py
, u_int width
, int regex
)
4006 struct grid
*gd
= data
->backing
->grid
;
4007 struct grid_cell gc
;
4008 u_int i
, b
, w
= width
, sx
= gd
->sx
, sy
= gd
->sy
;
4010 if (window_copy_search_mark_at(data
, px
, py
, &b
) == 0) {
4011 width
= window_copy_clip_width(width
, b
, sx
, sy
);
4013 for (i
= b
; i
< b
+ w
; i
++) {
4015 grid_get_cell(gd
, px
+ (i
- b
), py
, &gc
);
4016 if (gc
.flags
& GRID_FLAG_TAB
)
4017 w
+= gc
.data
.width
- 1;
4018 w
= window_copy_clip_width(w
, b
, sx
, sy
);
4020 if (data
->searchmark
[i
] != 0)
4022 data
->searchmark
[i
] = data
->searchgen
;
4024 if (data
->searchgen
== UCHAR_MAX
)
4025 data
->searchgen
= 1;
4034 window_copy_search_marks(struct window_mode_entry
*wme
, struct screen
*ssp
,
4035 int regex
, int visible_only
)
4037 struct window_copy_mode_data
*data
= wme
->data
;
4038 struct screen
*s
= data
->backing
, ss
;
4039 struct screen_write_ctx ctx
;
4040 struct grid
*gd
= s
->grid
;
4041 struct grid_cell gc
;
4042 int found
, cis
, stopped
= 0;
4043 int cflags
= REG_EXTENDED
;
4044 u_int px
, py
, nfound
= 0, width
;
4045 u_int ssize
= 1, start
, end
, sx
= gd
->sx
;
4049 uint64_t stop
= 0, tstart
, t
;
4052 width
= screen_write_strlen("%s", data
->searchstr
);
4053 screen_init(&ss
, width
, 1, 0);
4054 screen_write_start(&ctx
, &ss
);
4055 screen_write_nputs(&ctx
, -1, &grid_default_cell
, "%s",
4057 screen_write_stop(&ctx
);
4060 width
= screen_size_x(ssp
);
4062 cis
= window_copy_is_lowercase(data
->searchstr
);
4065 sbuf
= xmalloc(ssize
);
4067 sbuf
= window_copy_stringify(ssp
->grid
, 0, 0, ssp
->grid
->sx
,
4070 cflags
|= REG_ICASE
;
4071 if (regcomp(®
, sbuf
, cflags
) != 0) {
4077 tstart
= get_timer();
4080 window_copy_visible_lines(data
, &start
, &end
);
4083 end
= gd
->hsize
+ sy
;
4084 stop
= get_timer() + WINDOW_COPY_SEARCH_ALL_TIMEOUT
;
4088 free(data
->searchmark
);
4089 data
->searchmark
= xcalloc(sx
, sy
);
4090 data
->searchgen
= 1;
4092 for (py
= start
; py
< end
; py
++) {
4096 found
= window_copy_search_lr_regex(gd
,
4097 &px
, &width
, py
, px
, sx
, ®
);
4098 grid_get_cell(gd
, px
+ width
- 1, py
, &gc
);
4099 if (gc
.data
.width
> 2)
4100 width
+= gc
.data
.width
- 1;
4104 found
= window_copy_search_lr(gd
, ssp
->grid
,
4105 &px
, py
, px
, sx
, cis
);
4110 px
+= window_copy_search_mark_match(data
, px
, py
, width
,
4115 if (t
- tstart
> WINDOW_COPY_SEARCH_TIMEOUT
) {
4119 if (stop
!= 0 && t
> stop
) {
4124 if (data
->timeout
) {
4125 window_copy_clear_marks(wme
);
4129 if (stopped
&& stop
!= 0) {
4130 /* Try again but just the visible context. */
4131 window_copy_visible_lines(data
, &start
, &end
);
4136 if (!visible_only
) {
4139 data
->searchcount
= 1000;
4140 else if (nfound
> 100)
4141 data
->searchcount
= 100;
4142 else if (nfound
> 10)
4143 data
->searchcount
= 10;
4145 data
->searchcount
= -1;
4146 data
->searchmore
= 1;
4148 data
->searchcount
= nfound
;
4149 data
->searchmore
= 0;
4162 window_copy_clear_marks(struct window_mode_entry
*wme
)
4164 struct window_copy_mode_data
*data
= wme
->data
;
4166 free(data
->searchmark
);
4167 data
->searchmark
= NULL
;
4171 window_copy_search_up(struct window_mode_entry
*wme
, int regex
)
4173 return (window_copy_search(wme
, 0, regex
));
4177 window_copy_search_down(struct window_mode_entry
*wme
, int regex
)
4179 return (window_copy_search(wme
, 1, regex
));
4183 window_copy_goto_line(struct window_mode_entry
*wme
, const char *linestr
)
4185 struct window_copy_mode_data
*data
= wme
->data
;
4189 lineno
= strtonum(linestr
, -1, INT_MAX
, &errstr
);
4192 if (lineno
< 0 || (u_int
)lineno
> screen_hsize(data
->backing
))
4193 lineno
= screen_hsize(data
->backing
);
4196 window_copy_update_selection(wme
, 1, 0);
4197 window_copy_redraw_screen(wme
);
4201 window_copy_match_start_end(struct window_copy_mode_data
*data
, u_int at
,
4202 u_int
*start
, u_int
*end
)
4204 struct grid
*gd
= data
->backing
->grid
;
4205 u_int last
= (gd
->sy
* gd
->sx
) - 1;
4206 u_char mark
= data
->searchmark
[at
];
4209 while (*start
!= 0 && data
->searchmark
[*start
] == mark
)
4211 if (data
->searchmark
[*start
] != mark
)
4213 while (*end
!= last
&& data
->searchmark
[*end
] == mark
)
4215 if (data
->searchmark
[*end
] != mark
)
4220 window_copy_match_at_cursor(struct window_copy_mode_data
*data
)
4222 struct grid
*gd
= data
->backing
->grid
;
4223 struct grid_cell gc
;
4224 u_int at
, start
, end
, cy
, px
, py
;
4225 u_int sx
= screen_size_x(data
->backing
);
4229 if (data
->searchmark
== NULL
)
4232 cy
= screen_hsize(data
->backing
) - data
->oy
+ data
->cy
;
4233 if (window_copy_search_mark_at(data
, data
->cx
, cy
, &at
) != 0)
4235 if (data
->searchmark
[at
] == 0) {
4236 /* Allow one position after the match. */
4237 if (at
== 0 || data
->searchmark
[--at
] == 0)
4240 window_copy_match_start_end(data
, at
, &start
, &end
);
4243 * Cells will not be set in the marked array unless they are valid text
4244 * and wrapping will be taken care of, so we can just copy.
4246 for (at
= start
; at
<= end
; at
++) {
4248 px
= at
- (py
* sx
);
4250 grid_get_cell(gd
, px
, gd
->hsize
+ py
- data
->oy
, &gc
);
4251 if (gc
.flags
& GRID_FLAG_TAB
) {
4252 buf
= xrealloc(buf
, len
+ 2);
4256 buf
= xrealloc(buf
, len
+ gc
.data
.size
+ 1);
4257 memcpy(buf
+ len
, gc
.data
.data
, gc
.data
.size
);
4258 len
+= gc
.data
.size
;
4267 window_copy_update_style(struct window_mode_entry
*wme
, u_int fx
, u_int fy
,
4268 struct grid_cell
*gc
, const struct grid_cell
*mgc
,
4269 const struct grid_cell
*cgc
, const struct grid_cell
*mkgc
)
4271 struct window_pane
*wp
= wme
->wp
;
4272 struct window_copy_mode_data
*data
= wme
->data
;
4273 u_int mark
, start
, end
, cy
, cursor
, current
;
4274 int inv
= 0, found
= 0;
4277 if (data
->showmark
&& fy
== data
->my
) {
4278 gc
->attr
= mkgc
->attr
;
4291 if (data
->searchmark
== NULL
)
4294 if (window_copy_search_mark_at(data
, fx
, fy
, ¤t
) != 0)
4296 mark
= data
->searchmark
[current
];
4300 cy
= screen_hsize(data
->backing
) - data
->oy
+ data
->cy
;
4301 if (window_copy_search_mark_at(data
, data
->cx
, cy
, &cursor
) == 0) {
4302 keys
= options_get_number(wp
->window
->options
, "mode-keys");
4304 keys
== MODEKEY_EMACS
&&
4305 data
->searchdirection
) {
4306 if (data
->searchmark
[cursor
- 1] == mark
) {
4310 } else if (data
->searchmark
[cursor
] == mark
)
4313 window_copy_match_start_end(data
, cursor
, &start
, &end
);
4314 if (current
>= start
&& current
<= end
) {
4315 gc
->attr
= cgc
->attr
;
4329 gc
->attr
= mgc
->attr
;
4341 window_copy_write_one(struct window_mode_entry
*wme
,
4342 struct screen_write_ctx
*ctx
, u_int py
, u_int fy
, u_int nx
,
4343 const struct grid_cell
*mgc
, const struct grid_cell
*cgc
,
4344 const struct grid_cell
*mkgc
)
4346 struct window_copy_mode_data
*data
= wme
->data
;
4347 struct grid
*gd
= data
->backing
->grid
;
4348 struct grid_cell gc
;
4351 screen_write_cursormove(ctx
, 0, py
, 0);
4352 for (fx
= 0; fx
< nx
; fx
++) {
4353 grid_get_cell(gd
, fx
, fy
, &gc
);
4354 if (fx
+ gc
.data
.width
<= nx
) {
4355 window_copy_update_style(wme
, fx
, fy
, &gc
, mgc
, cgc
,
4357 screen_write_cell(ctx
, &gc
);
4363 window_copy_get_current_offset(struct window_pane
*wp
, u_int
*offset
,
4366 struct window_mode_entry
*wme
= TAILQ_FIRST(&wp
->modes
);
4367 struct window_copy_mode_data
*data
= wme
->data
;
4372 hsize
= screen_hsize(data
->backing
);
4374 *offset
= hsize
- data
->oy
;
4380 window_copy_write_line(struct window_mode_entry
*wme
,
4381 struct screen_write_ctx
*ctx
, u_int py
)
4383 struct window_pane
*wp
= wme
->wp
;
4384 struct window_copy_mode_data
*data
= wme
->data
;
4385 struct screen
*s
= &data
->screen
;
4386 struct options
*oo
= wp
->window
->options
;
4387 struct grid_cell gc
, mgc
, cgc
, mkgc
;
4388 u_int sx
= screen_size_x(s
);
4389 u_int hsize
= screen_hsize(data
->backing
);
4392 struct format_tree
*ft
;
4394 style_apply(&gc
, oo
, "mode-style", NULL
);
4395 gc
.flags
|= GRID_FLAG_NOPALETTE
;
4396 style_apply(&mgc
, oo
, "copy-mode-match-style", NULL
);
4397 mgc
.flags
|= GRID_FLAG_NOPALETTE
;
4398 style_apply(&cgc
, oo
, "copy-mode-current-match-style", NULL
);
4399 cgc
.flags
|= GRID_FLAG_NOPALETTE
;
4400 style_apply(&mkgc
, oo
, "copy-mode-mark-style", NULL
);
4401 mkgc
.flags
|= GRID_FLAG_NOPALETTE
;
4403 window_copy_write_one(wme
, ctx
, py
, hsize
- data
->oy
+ py
,
4404 screen_size_x(s
), &mgc
, &cgc
, &mkgc
);
4406 if (py
== 0 && s
->rupper
< s
->rlower
&& !data
->hide_position
) {
4407 value
= options_get_string(oo
, "copy-mode-position-format");
4408 if (*value
!= '\0') {
4409 ft
= format_create_defaults(NULL
, NULL
, NULL
, NULL
, wp
);
4410 expanded
= format_expand(ft
, value
);
4411 if (*expanded
!= '\0') {
4412 screen_write_cursormove(ctx
, 0, 0, 0);
4413 format_draw(ctx
, &gc
, sx
, expanded
, NULL
, 0);
4420 if (py
== data
->cy
&& data
->cx
== screen_size_x(s
)) {
4421 screen_write_cursormove(ctx
, screen_size_x(s
) - 1, py
, 0);
4422 screen_write_putc(ctx
, &grid_default_cell
, '$');
4427 window_copy_write_lines(struct window_mode_entry
*wme
,
4428 struct screen_write_ctx
*ctx
, u_int py
, u_int ny
)
4432 for (yy
= py
; yy
< py
+ ny
; yy
++)
4433 window_copy_write_line(wme
, ctx
, py
);
4437 window_copy_redraw_selection(struct window_mode_entry
*wme
, u_int old_y
)
4439 struct window_copy_mode_data
*data
= wme
->data
;
4440 struct grid
*gd
= data
->backing
->grid
;
4441 u_int new_y
, start
, end
;
4444 if (old_y
<= new_y
) {
4453 * In word selection mode the first word on the line below the cursor
4454 * might be selected, so add this line to the redraw area.
4456 if (data
->selflag
== SEL_WORD
) {
4457 /* Last grid line in data coordinates. */
4458 if (end
< gd
->sy
+ data
->oy
- 1)
4461 window_copy_redraw_lines(wme
, start
, end
- start
+ 1);
4465 window_copy_redraw_lines(struct window_mode_entry
*wme
, u_int py
, u_int ny
)
4467 struct window_pane
*wp
= wme
->wp
;
4468 struct window_copy_mode_data
*data
= wme
->data
;
4469 struct screen_write_ctx ctx
;
4472 screen_write_start_pane(&ctx
, wp
, NULL
);
4473 for (i
= py
; i
< py
+ ny
; i
++)
4474 window_copy_write_line(wme
, &ctx
, i
);
4475 screen_write_cursormove(&ctx
, data
->cx
, data
->cy
, 0);
4476 screen_write_stop(&ctx
);
4478 wp
->flags
|= PANE_REDRAWSCROLLBAR
;
4482 window_copy_redraw_screen(struct window_mode_entry
*wme
)
4484 struct window_copy_mode_data
*data
= wme
->data
;
4486 window_copy_redraw_lines(wme
, 0, screen_size_y(&data
->screen
));
4490 window_copy_synchronize_cursor_end(struct window_mode_entry
*wme
, int begin
,
4493 struct window_copy_mode_data
*data
= wme
->data
;
4497 yy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
4498 switch (data
->selflag
) {
4503 if (data
->dy
> yy
|| (data
->dy
== yy
&& data
->dx
> xx
)) {
4504 /* Right to left selection. */
4505 window_copy_cursor_previous_word_pos(wme
,
4506 data
->separators
, &xx
, &yy
);
4509 /* Reset the end. */
4510 data
->endselx
= data
->endselrx
;
4511 data
->endsely
= data
->endselry
;
4513 /* Left to right selection. */
4514 if (xx
>= window_copy_find_length(wme
, yy
) ||
4515 !window_copy_in_set(wme
, xx
+ 1, yy
, WHITESPACE
)) {
4516 window_copy_cursor_next_word_end_pos(wme
,
4517 data
->separators
, &xx
, &yy
);
4520 /* Reset the start. */
4521 data
->selx
= data
->selrx
;
4522 data
->sely
= data
->selry
;
4529 if (data
->dy
> yy
) {
4530 /* Right to left selection. */
4534 /* Reset the end. */
4535 data
->endselx
= data
->endselrx
;
4536 data
->endsely
= data
->endselry
;
4538 /* Left to right selection. */
4539 if (yy
< data
->endselry
)
4540 yy
= data
->endselry
;
4541 xx
= window_copy_find_length(wme
, yy
);
4543 /* Reset the start. */
4544 data
->selx
= data
->selrx
;
4545 data
->sely
= data
->selry
;
4561 window_copy_synchronize_cursor(struct window_mode_entry
*wme
, int no_reset
)
4563 struct window_copy_mode_data
*data
= wme
->data
;
4565 switch (data
->cursordrag
) {
4566 case CURSORDRAG_ENDSEL
:
4567 window_copy_synchronize_cursor_end(wme
, 0, no_reset
);
4569 case CURSORDRAG_SEL
:
4570 window_copy_synchronize_cursor_end(wme
, 1, no_reset
);
4572 case CURSORDRAG_NONE
:
4578 window_copy_update_cursor(struct window_mode_entry
*wme
, u_int cx
, u_int cy
)
4580 struct window_pane
*wp
= wme
->wp
;
4581 struct window_copy_mode_data
*data
= wme
->data
;
4582 struct screen
*s
= &data
->screen
;
4583 struct screen_write_ctx ctx
;
4584 u_int old_cx
, old_cy
;
4586 old_cx
= data
->cx
; old_cy
= data
->cy
;
4587 data
->cx
= cx
; data
->cy
= cy
;
4588 if (old_cx
== screen_size_x(s
))
4589 window_copy_redraw_lines(wme
, old_cy
, 1);
4590 if (data
->cx
== screen_size_x(s
))
4591 window_copy_redraw_lines(wme
, data
->cy
, 1);
4593 screen_write_start_pane(&ctx
, wp
, NULL
);
4594 screen_write_cursormove(&ctx
, data
->cx
, data
->cy
, 0);
4595 screen_write_stop(&ctx
);
4600 window_copy_start_selection(struct window_mode_entry
*wme
)
4602 struct window_copy_mode_data
*data
= wme
->data
;
4604 data
->selx
= data
->cx
;
4605 data
->sely
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
4607 data
->endselx
= data
->selx
;
4608 data
->endsely
= data
->sely
;
4610 data
->cursordrag
= CURSORDRAG_ENDSEL
;
4612 window_copy_set_selection(wme
, 1, 0);
4616 window_copy_adjust_selection(struct window_mode_entry
*wme
, u_int
*selx
,
4619 struct window_copy_mode_data
*data
= wme
->data
;
4620 struct screen
*s
= &data
->screen
;
4627 ty
= screen_hsize(data
->backing
) - data
->oy
;
4629 relpos
= WINDOW_COPY_REL_POS_ABOVE
;
4630 if (!data
->rectflag
)
4633 } else if (sy
> ty
+ screen_size_y(s
) - 1) {
4634 relpos
= WINDOW_COPY_REL_POS_BELOW
;
4635 if (!data
->rectflag
)
4636 sx
= screen_size_x(s
) - 1;
4637 sy
= screen_size_y(s
) - 1;
4639 relpos
= WINDOW_COPY_REL_POS_ON_SCREEN
;
4649 window_copy_update_selection(struct window_mode_entry
*wme
, int may_redraw
,
4652 struct window_copy_mode_data
*data
= wme
->data
;
4653 struct screen
*s
= &data
->screen
;
4655 if (s
->sel
== NULL
&& data
->lineflag
== LINE_SEL_NONE
)
4657 return (window_copy_set_selection(wme
, may_redraw
, no_reset
));
4661 window_copy_set_selection(struct window_mode_entry
*wme
, int may_redraw
,
4664 struct window_pane
*wp
= wme
->wp
;
4665 struct window_copy_mode_data
*data
= wme
->data
;
4666 struct screen
*s
= &data
->screen
;
4667 struct options
*oo
= wp
->window
->options
;
4668 struct grid_cell gc
;
4669 u_int sx
, sy
, cy
, endsx
, endsy
;
4670 int startrelpos
, endrelpos
;
4672 window_copy_synchronize_cursor(wme
, no_reset
);
4674 /* Adjust the selection. */
4677 startrelpos
= window_copy_adjust_selection(wme
, &sx
, &sy
);
4679 /* Adjust the end of selection. */
4680 endsx
= data
->endselx
;
4681 endsy
= data
->endsely
;
4682 endrelpos
= window_copy_adjust_selection(wme
, &endsx
, &endsy
);
4684 /* Selection is outside of the current screen */
4685 if (startrelpos
== endrelpos
&&
4686 startrelpos
!= WINDOW_COPY_REL_POS_ON_SCREEN
) {
4687 screen_hide_selection(s
);
4691 /* Set colours and selection. */
4692 style_apply(&gc
, oo
, "mode-style", NULL
);
4693 gc
.flags
|= GRID_FLAG_NOPALETTE
;
4694 screen_set_selection(s
, sx
, sy
, endsx
, endsy
, data
->rectflag
,
4695 data
->modekeys
, &gc
);
4697 if (data
->rectflag
&& may_redraw
) {
4699 * Can't rely on the caller to redraw the right lines for
4700 * rectangle selection - find the highest line and the number
4701 * of lines, and redraw just past that in both directions
4704 if (data
->cursordrag
== CURSORDRAG_ENDSEL
) {
4706 window_copy_redraw_lines(wme
, sy
, cy
- sy
+ 1);
4708 window_copy_redraw_lines(wme
, cy
, sy
- cy
+ 1);
4711 window_copy_redraw_lines(wme
, endsy
,
4714 window_copy_redraw_lines(wme
, cy
,
4724 window_copy_get_selection(struct window_mode_entry
*wme
, size_t *len
)
4726 struct window_pane
*wp
= wme
->wp
;
4727 struct window_copy_mode_data
*data
= wme
->data
;
4728 struct screen
*s
= &data
->screen
;
4731 u_int i
, xx
, yy
, sx
, sy
, ex
, ey
, ey_last
;
4732 u_int firstsx
, lastex
, restex
, restsx
, selx
;
4735 if (data
->screen
.sel
== NULL
&& data
->lineflag
== LINE_SEL_NONE
) {
4736 buf
= window_copy_match_at_cursor(data
);
4750 * The selection extends from selx,sely to (adjusted) cx,cy on
4754 /* Find start and end. */
4757 if (yy
< data
->sely
|| (yy
== data
->sely
&& xx
< data
->selx
)) {
4759 ex
= data
->selx
; ey
= data
->sely
;
4761 sx
= data
->selx
; sy
= data
->sely
;
4765 /* Trim ex to end of line. */
4766 ey_last
= window_copy_find_length(wme
, ey
);
4771 * Deal with rectangle-copy if necessary; four situations: start of
4772 * first line (firstsx), end of last line (lastex), start (restsx) and
4773 * end (restex) of all other lines.
4775 xx
= screen_size_x(s
);
4778 * Behave according to mode-keys. If it is emacs, copy like emacs,
4779 * keeping the top-left-most character, and dropping the
4780 * bottom-right-most, regardless of copy direction. If it is vi, also
4781 * keep bottom-right-most character.
4783 keys
= options_get_number(wp
->window
->options
, "mode-keys");
4784 if (data
->rectflag
) {
4786 * Need to ignore the column with the cursor in it, which for
4787 * rectangular copy means knowing which side the cursor is on.
4789 if (data
->cursordrag
== CURSORDRAG_ENDSEL
)
4792 selx
= data
->endselx
;
4793 if (selx
< data
->cx
) {
4794 /* Selection start is on the left. */
4795 if (keys
== MODEKEY_EMACS
) {
4800 lastex
= data
->cx
+ 1;
4801 restex
= data
->cx
+ 1;
4806 /* Cursor is on the left. */
4813 if (keys
== MODEKEY_EMACS
)
4822 /* Copy the lines. */
4823 for (i
= sy
; i
<= ey
; i
++) {
4824 window_copy_copy_line(wme
, &buf
, &off
, i
,
4825 (i
== sy
? firstsx
: restsx
),
4826 (i
== ey
? lastex
: restex
));
4829 /* Don't bother if no data. */
4835 /* Remove final \n (unless at end in vi mode). */
4836 if (keys
== MODEKEY_EMACS
|| lastex
<= ey_last
) {
4837 if (~grid_get_line(data
->backing
->grid
, ey
)->flags
&
4838 GRID_LINE_WRAPPED
|| lastex
!= ey_last
)
4846 window_copy_copy_buffer(struct window_mode_entry
*wme
, const char *prefix
,
4847 void *buf
, size_t len
, int set_paste
, int set_clip
)
4849 struct window_pane
*wp
= wme
->wp
;
4850 struct screen_write_ctx ctx
;
4853 options_get_number(global_options
, "set-clipboard") != 0) {
4854 screen_write_start_pane(&ctx
, wp
, NULL
);
4855 screen_write_setselection(&ctx
, "", buf
, len
);
4856 screen_write_stop(&ctx
);
4857 notify_pane("pane-set-clipboard", wp
);
4861 paste_add(prefix
, buf
, len
);
4865 window_copy_pipe_run(struct window_mode_entry
*wme
, struct session
*s
,
4866 const char *cmd
, size_t *len
)
4871 buf
= window_copy_get_selection(wme
, len
);
4872 if (cmd
== NULL
|| *cmd
== '\0')
4873 cmd
= options_get_string(global_options
, "copy-command");
4874 if (cmd
!= NULL
&& *cmd
!= '\0') {
4875 job
= job_run(cmd
, 0, NULL
, NULL
, s
, NULL
, NULL
, NULL
, NULL
,
4876 NULL
, JOB_NOWAIT
, -1, -1);
4877 bufferevent_write(job_get_event(job
), buf
, *len
);
4883 window_copy_pipe(struct window_mode_entry
*wme
, struct session
*s
,
4888 window_copy_pipe_run(wme
, s
, cmd
, &len
);
4892 window_copy_copy_pipe(struct window_mode_entry
*wme
, struct session
*s
,
4893 const char *prefix
, const char *cmd
, int set_paste
, int set_clip
)
4898 buf
= window_copy_pipe_run(wme
, s
, cmd
, &len
);
4900 window_copy_copy_buffer(wme
, prefix
, buf
, len
, set_paste
,
4905 window_copy_copy_selection(struct window_mode_entry
*wme
, const char *prefix
,
4906 int set_paste
, int set_clip
)
4911 buf
= window_copy_get_selection(wme
, &len
);
4913 window_copy_copy_buffer(wme
, prefix
, buf
, len
, set_paste
,
4918 window_copy_append_selection(struct window_mode_entry
*wme
)
4920 struct window_pane
*wp
= wme
->wp
;
4922 struct paste_buffer
*pb
;
4923 const char *bufdata
, *bufname
= NULL
;
4924 size_t len
, bufsize
;
4925 struct screen_write_ctx ctx
;
4927 buf
= window_copy_get_selection(wme
, &len
);
4931 if (options_get_number(global_options
, "set-clipboard") != 0) {
4932 screen_write_start_pane(&ctx
, wp
, NULL
);
4933 screen_write_setselection(&ctx
, "", buf
, len
);
4934 screen_write_stop(&ctx
);
4935 notify_pane("pane-set-clipboard", wp
);
4938 pb
= paste_get_top(&bufname
);
4940 bufdata
= paste_buffer_data(pb
, &bufsize
);
4941 buf
= xrealloc(buf
, len
+ bufsize
);
4942 memmove(buf
+ bufsize
, buf
, len
);
4943 memcpy(buf
, bufdata
, bufsize
);
4946 if (paste_set(buf
, len
, bufname
, NULL
) != 0)
4951 window_copy_copy_line(struct window_mode_entry
*wme
, char **buf
, size_t *off
,
4952 u_int sy
, u_int sx
, u_int ex
)
4954 struct window_copy_mode_data
*data
= wme
->data
;
4955 struct grid
*gd
= data
->backing
->grid
;
4956 struct grid_cell gc
;
4957 struct grid_line
*gl
;
4958 struct utf8_data ud
;
4959 u_int i
, xx
, wrapped
= 0;
4966 * Work out if the line was wrapped at the screen edge and all of it is
4969 gl
= grid_get_line(gd
, sy
);
4970 if (gl
->flags
& GRID_LINE_WRAPPED
&& gl
->cellsize
<= gd
->sx
)
4973 /* If the line was wrapped, don't strip spaces (use the full length). */
4977 xx
= window_copy_find_length(wme
, sy
);
4984 for (i
= sx
; i
< ex
; i
++) {
4985 grid_get_cell(gd
, i
, sy
, &gc
);
4986 if (gc
.flags
& GRID_FLAG_PADDING
)
4988 if (gc
.flags
& GRID_FLAG_TAB
)
4989 utf8_set(&ud
, '\t');
4991 utf8_copy(&ud
, &gc
.data
);
4992 if (ud
.size
== 1 && (gc
.attr
& GRID_ATTR_CHARSET
)) {
4993 s
= tty_acs_get(NULL
, ud
.data
[0]);
4994 if (s
!= NULL
&& strlen(s
) <= sizeof ud
.data
) {
4995 ud
.size
= strlen(s
);
4996 memcpy(ud
.data
, s
, ud
.size
);
5000 *buf
= xrealloc(*buf
, (*off
) + ud
.size
);
5001 memcpy(*buf
+ *off
, ud
.data
, ud
.size
);
5006 /* Only add a newline if the line wasn't wrapped. */
5007 if (!wrapped
|| ex
!= xx
) {
5008 *buf
= xrealloc(*buf
, (*off
) + 1);
5009 (*buf
)[(*off
)++] = '\n';
5014 window_copy_clear_selection(struct window_mode_entry
*wme
)
5016 struct window_copy_mode_data
*data
= wme
->data
;
5019 screen_clear_selection(&data
->screen
);
5021 data
->cursordrag
= CURSORDRAG_NONE
;
5022 data
->lineflag
= LINE_SEL_NONE
;
5023 data
->selflag
= SEL_CHAR
;
5025 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5026 px
= window_copy_find_length(wme
, py
);
5028 window_copy_update_cursor(wme
, px
, data
->cy
);
5032 window_copy_in_set(struct window_mode_entry
*wme
, u_int px
, u_int py
,
5035 struct window_copy_mode_data
*data
= wme
->data
;
5037 return (grid_in_set(data
->backing
->grid
, px
, py
, set
));
5041 window_copy_find_length(struct window_mode_entry
*wme
, u_int py
)
5043 struct window_copy_mode_data
*data
= wme
->data
;
5045 return (grid_line_length(data
->backing
->grid
, py
));
5049 window_copy_cursor_start_of_line(struct window_mode_entry
*wme
)
5051 struct window_copy_mode_data
*data
= wme
->data
;
5052 struct screen
*back_s
= data
->backing
;
5053 struct grid_reader gr
;
5054 u_int px
, py
, oldy
, hsize
;
5057 hsize
= screen_hsize(back_s
);
5058 py
= hsize
+ data
->cy
- data
->oy
;
5061 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5062 grid_reader_cursor_start_of_line(&gr
, 1);
5063 grid_reader_get_cursor(&gr
, &px
, &py
);
5064 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
, py
);
5068 window_copy_cursor_back_to_indentation(struct window_mode_entry
*wme
)
5070 struct window_copy_mode_data
*data
= wme
->data
;
5071 struct screen
*back_s
= data
->backing
;
5072 struct grid_reader gr
;
5073 u_int px
, py
, oldy
, hsize
;
5076 hsize
= screen_hsize(back_s
);
5077 py
= hsize
+ data
->cy
- data
->oy
;
5080 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5081 grid_reader_cursor_back_to_indentation(&gr
);
5082 grid_reader_get_cursor(&gr
, &px
, &py
);
5083 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
, py
);
5087 window_copy_cursor_end_of_line(struct window_mode_entry
*wme
)
5089 struct window_copy_mode_data
*data
= wme
->data
;
5090 struct screen
*back_s
= data
->backing
;
5091 struct grid_reader gr
;
5092 u_int px
, py
, oldy
, hsize
;
5095 hsize
= screen_hsize(back_s
);
5096 py
= hsize
+ data
->cy
- data
->oy
;
5099 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5100 if (data
->screen
.sel
!= NULL
&& data
->rectflag
)
5101 grid_reader_cursor_end_of_line(&gr
, 1, 1);
5103 grid_reader_cursor_end_of_line(&gr
, 1, 0);
5104 grid_reader_get_cursor(&gr
, &px
, &py
);
5105 window_copy_acquire_cursor_down(wme
, hsize
, screen_size_y(back_s
),
5106 data
->oy
, oldy
, px
, py
, 0);
5110 window_copy_other_end(struct window_mode_entry
*wme
)
5112 struct window_copy_mode_data
*data
= wme
->data
;
5113 struct screen
*s
= &data
->screen
;
5114 u_int selx
, sely
, cy
, yy
, hsize
;
5116 if (s
->sel
== NULL
&& data
->lineflag
== LINE_SEL_NONE
)
5119 if (data
->lineflag
== LINE_SEL_LEFT_RIGHT
)
5120 data
->lineflag
= LINE_SEL_RIGHT_LEFT
;
5121 else if (data
->lineflag
== LINE_SEL_RIGHT_LEFT
)
5122 data
->lineflag
= LINE_SEL_LEFT_RIGHT
;
5124 switch (data
->cursordrag
) {
5125 case CURSORDRAG_NONE
:
5126 case CURSORDRAG_SEL
:
5127 data
->cursordrag
= CURSORDRAG_ENDSEL
;
5129 case CURSORDRAG_ENDSEL
:
5130 data
->cursordrag
= CURSORDRAG_SEL
;
5134 selx
= data
->endselx
;
5135 sely
= data
->endsely
;
5136 if (data
->cursordrag
== CURSORDRAG_SEL
) {
5142 yy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5146 hsize
= screen_hsize(data
->backing
);
5147 if (sely
< hsize
- data
->oy
) { /* above */
5148 data
->oy
= hsize
- sely
;
5150 } else if (sely
> hsize
- data
->oy
+ screen_size_y(s
)) { /* below */
5151 data
->oy
= hsize
- sely
+ screen_size_y(s
) - 1;
5152 data
->cy
= screen_size_y(s
) - 1;
5154 data
->cy
= cy
+ sely
- yy
;
5156 window_copy_update_selection(wme
, 1, 1);
5157 window_copy_redraw_screen(wme
);
5161 window_copy_cursor_left(struct window_mode_entry
*wme
)
5163 struct window_copy_mode_data
*data
= wme
->data
;
5164 struct screen
*back_s
= data
->backing
;
5165 struct grid_reader gr
;
5166 u_int px
, py
, oldy
, hsize
;
5169 hsize
= screen_hsize(back_s
);
5170 py
= hsize
+ data
->cy
- data
->oy
;
5173 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5174 grid_reader_cursor_left(&gr
, 1);
5175 grid_reader_get_cursor(&gr
, &px
, &py
);
5176 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
, py
);
5180 window_copy_cursor_right(struct window_mode_entry
*wme
, int all
)
5182 struct window_copy_mode_data
*data
= wme
->data
;
5183 struct screen
*back_s
= data
->backing
;
5184 struct grid_reader gr
;
5185 u_int px
, py
, oldy
, hsize
;
5188 hsize
= screen_hsize(back_s
);
5189 py
= hsize
+ data
->cy
- data
->oy
;
5192 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5193 grid_reader_cursor_right(&gr
, 1, all
);
5194 grid_reader_get_cursor(&gr
, &px
, &py
);
5195 window_copy_acquire_cursor_down(wme
, hsize
, screen_size_y(back_s
),
5196 data
->oy
, oldy
, px
, py
, 0);
5200 window_copy_cursor_up(struct window_mode_entry
*wme
, int scroll_only
)
5202 struct window_copy_mode_data
*data
= wme
->data
;
5203 struct screen
*s
= &data
->screen
;
5204 u_int ox
, oy
, px
, py
;
5207 norectsel
= data
->screen
.sel
== NULL
|| !data
->rectflag
;
5208 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5209 ox
= window_copy_find_length(wme
, oy
);
5210 if (norectsel
&& data
->cx
!= ox
) {
5211 data
->lastcx
= data
->cx
;
5215 if (data
->lineflag
== LINE_SEL_LEFT_RIGHT
&& oy
== data
->sely
)
5216 window_copy_other_end(wme
);
5218 if (scroll_only
|| data
->cy
== 0) {
5220 data
->cx
= data
->lastcx
;
5221 window_copy_scroll_down(wme
, 1);
5223 if (data
->cy
== screen_size_y(s
) - 1)
5224 window_copy_redraw_lines(wme
, data
->cy
, 1);
5226 window_copy_redraw_lines(wme
, data
->cy
, 2);
5230 window_copy_update_cursor(wme
, data
->lastcx
,
5233 window_copy_update_cursor(wme
, data
->cx
, data
->cy
- 1);
5234 if (window_copy_update_selection(wme
, 1, 0)) {
5235 if (data
->cy
== screen_size_y(s
) - 1)
5236 window_copy_redraw_lines(wme
, data
->cy
, 1);
5238 window_copy_redraw_lines(wme
, data
->cy
, 2);
5243 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5244 px
= window_copy_find_length(wme
, py
);
5245 if ((data
->cx
>= data
->lastsx
&& data
->cx
!= px
) ||
5248 window_copy_update_cursor(wme
, px
, data
->cy
);
5249 if (window_copy_update_selection(wme
, 1, 0))
5250 window_copy_redraw_lines(wme
, data
->cy
, 1);
5254 if (data
->lineflag
== LINE_SEL_LEFT_RIGHT
)
5256 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5258 px
= screen_size_x(data
->backing
);
5260 px
= window_copy_find_length(wme
, py
);
5261 window_copy_update_cursor(wme
, px
, data
->cy
);
5262 if (window_copy_update_selection(wme
, 1, 0))
5263 window_copy_redraw_lines(wme
, data
->cy
, 1);
5265 else if (data
->lineflag
== LINE_SEL_RIGHT_LEFT
)
5267 window_copy_update_cursor(wme
, 0, data
->cy
);
5268 if (window_copy_update_selection(wme
, 1, 0))
5269 window_copy_redraw_lines(wme
, data
->cy
, 1);
5274 window_copy_cursor_down(struct window_mode_entry
*wme
, int scroll_only
)
5276 struct window_copy_mode_data
*data
= wme
->data
;
5277 struct screen
*s
= &data
->screen
;
5278 u_int ox
, oy
, px
, py
;
5281 norectsel
= data
->screen
.sel
== NULL
|| !data
->rectflag
;
5282 oy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5283 ox
= window_copy_find_length(wme
, oy
);
5284 if (norectsel
&& data
->cx
!= ox
) {
5285 data
->lastcx
= data
->cx
;
5289 if (data
->lineflag
== LINE_SEL_RIGHT_LEFT
&& oy
== data
->endsely
)
5290 window_copy_other_end(wme
);
5292 if (scroll_only
|| data
->cy
== screen_size_y(s
) - 1) {
5294 data
->cx
= data
->lastcx
;
5295 window_copy_scroll_up(wme
, 1);
5296 if (scroll_only
&& data
->cy
> 0)
5297 window_copy_redraw_lines(wme
, data
->cy
- 1, 2);
5300 window_copy_update_cursor(wme
, data
->lastcx
,
5303 window_copy_update_cursor(wme
, data
->cx
, data
->cy
+ 1);
5304 if (window_copy_update_selection(wme
, 1, 0))
5305 window_copy_redraw_lines(wme
, data
->cy
- 1, 2);
5309 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5310 px
= window_copy_find_length(wme
, py
);
5311 if ((data
->cx
>= data
->lastsx
&& data
->cx
!= px
) ||
5314 window_copy_update_cursor(wme
, px
, data
->cy
);
5315 if (window_copy_update_selection(wme
, 1, 0))
5316 window_copy_redraw_lines(wme
, data
->cy
, 1);
5320 if (data
->lineflag
== LINE_SEL_LEFT_RIGHT
)
5322 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5324 px
= screen_size_x(data
->backing
);
5326 px
= window_copy_find_length(wme
, py
);
5327 window_copy_update_cursor(wme
, px
, data
->cy
);
5328 if (window_copy_update_selection(wme
, 1, 0))
5329 window_copy_redraw_lines(wme
, data
->cy
, 1);
5331 else if (data
->lineflag
== LINE_SEL_RIGHT_LEFT
)
5333 window_copy_update_cursor(wme
, 0, data
->cy
);
5334 if (window_copy_update_selection(wme
, 1, 0))
5335 window_copy_redraw_lines(wme
, data
->cy
, 1);
5340 window_copy_cursor_jump(struct window_mode_entry
*wme
)
5342 struct window_copy_mode_data
*data
= wme
->data
;
5343 struct screen
*back_s
= data
->backing
;
5344 struct grid_reader gr
;
5345 u_int px
, py
, oldy
, hsize
;
5348 hsize
= screen_hsize(back_s
);
5349 py
= hsize
+ data
->cy
- data
->oy
;
5352 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5353 if (grid_reader_cursor_jump(&gr
, data
->jumpchar
)) {
5354 grid_reader_get_cursor(&gr
, &px
, &py
);
5355 window_copy_acquire_cursor_down(wme
, hsize
,
5356 screen_size_y(back_s
), data
->oy
, oldy
, px
, py
, 0);
5361 window_copy_cursor_jump_back(struct window_mode_entry
*wme
)
5363 struct window_copy_mode_data
*data
= wme
->data
;
5364 struct screen
*back_s
= data
->backing
;
5365 struct grid_reader gr
;
5366 u_int px
, py
, oldy
, hsize
;
5369 hsize
= screen_hsize(back_s
);
5370 py
= hsize
+ data
->cy
- data
->oy
;
5373 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5374 grid_reader_cursor_left(&gr
, 0);
5375 if (grid_reader_cursor_jump_back(&gr
, data
->jumpchar
)) {
5376 grid_reader_get_cursor(&gr
, &px
, &py
);
5377 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
,
5383 window_copy_cursor_jump_to(struct window_mode_entry
*wme
)
5385 struct window_copy_mode_data
*data
= wme
->data
;
5386 struct screen
*back_s
= data
->backing
;
5387 struct grid_reader gr
;
5388 u_int px
, py
, oldy
, hsize
;
5391 hsize
= screen_hsize(back_s
);
5392 py
= hsize
+ data
->cy
- data
->oy
;
5395 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5396 if (grid_reader_cursor_jump(&gr
, data
->jumpchar
)) {
5397 grid_reader_cursor_left(&gr
, 1);
5398 grid_reader_get_cursor(&gr
, &px
, &py
);
5399 window_copy_acquire_cursor_down(wme
, hsize
,
5400 screen_size_y(back_s
), data
->oy
, oldy
, px
, py
, 0);
5405 window_copy_cursor_jump_to_back(struct window_mode_entry
*wme
)
5407 struct window_copy_mode_data
*data
= wme
->data
;
5408 struct screen
*back_s
= data
->backing
;
5409 struct grid_reader gr
;
5410 u_int px
, py
, oldy
, hsize
;
5413 hsize
= screen_hsize(back_s
);
5414 py
= hsize
+ data
->cy
- data
->oy
;
5417 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5418 grid_reader_cursor_left(&gr
, 0);
5419 grid_reader_cursor_left(&gr
, 0);
5420 if (grid_reader_cursor_jump_back(&gr
, data
->jumpchar
)) {
5421 grid_reader_cursor_right(&gr
, 1, 0);
5422 grid_reader_get_cursor(&gr
, &px
, &py
);
5423 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
,
5429 window_copy_cursor_next_word(struct window_mode_entry
*wme
,
5430 const char *separators
)
5432 struct window_copy_mode_data
*data
= wme
->data
;
5433 struct screen
*back_s
= data
->backing
;
5434 struct grid_reader gr
;
5435 u_int px
, py
, oldy
, hsize
;
5438 hsize
= screen_hsize(back_s
);
5439 py
= hsize
+ data
->cy
- data
->oy
;
5442 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5443 grid_reader_cursor_next_word(&gr
, separators
);
5444 grid_reader_get_cursor(&gr
, &px
, &py
);
5445 window_copy_acquire_cursor_down(wme
, hsize
, screen_size_y(back_s
),
5446 data
->oy
, oldy
, px
, py
, 0);
5449 /* Compute the next place where a word ends. */
5451 window_copy_cursor_next_word_end_pos(struct window_mode_entry
*wme
,
5452 const char *separators
, u_int
*ppx
, u_int
*ppy
)
5454 struct window_pane
*wp
= wme
->wp
;
5455 struct window_copy_mode_data
*data
= wme
->data
;
5456 struct options
*oo
= wp
->window
->options
;
5457 struct screen
*back_s
= data
->backing
;
5458 struct grid_reader gr
;
5459 u_int px
, py
, hsize
;
5462 hsize
= screen_hsize(back_s
);
5463 py
= hsize
+ data
->cy
- data
->oy
;
5465 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5466 if (options_get_number(oo
, "mode-keys") == MODEKEY_VI
) {
5467 if (!grid_reader_in_set(&gr
, WHITESPACE
))
5468 grid_reader_cursor_right(&gr
, 0, 0);
5469 grid_reader_cursor_next_word_end(&gr
, separators
);
5470 grid_reader_cursor_left(&gr
, 1);
5472 grid_reader_cursor_next_word_end(&gr
, separators
);
5473 grid_reader_get_cursor(&gr
, &px
, &py
);
5478 /* Move to the next place where a word ends. */
5480 window_copy_cursor_next_word_end(struct window_mode_entry
*wme
,
5481 const char *separators
, int no_reset
)
5483 struct window_pane
*wp
= wme
->wp
;
5484 struct window_copy_mode_data
*data
= wme
->data
;
5485 struct options
*oo
= wp
->window
->options
;
5486 struct screen
*back_s
= data
->backing
;
5487 struct grid_reader gr
;
5488 u_int px
, py
, oldy
, hsize
;
5491 hsize
= screen_hsize(back_s
);
5492 py
= hsize
+ data
->cy
- data
->oy
;
5495 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5496 if (options_get_number(oo
, "mode-keys") == MODEKEY_VI
) {
5497 if (!grid_reader_in_set(&gr
, WHITESPACE
))
5498 grid_reader_cursor_right(&gr
, 0, 0);
5499 grid_reader_cursor_next_word_end(&gr
, separators
);
5500 grid_reader_cursor_left(&gr
, 1);
5502 grid_reader_cursor_next_word_end(&gr
, separators
);
5503 grid_reader_get_cursor(&gr
, &px
, &py
);
5504 window_copy_acquire_cursor_down(wme
, hsize
, screen_size_y(back_s
),
5505 data
->oy
, oldy
, px
, py
, no_reset
);
5508 /* Compute the previous place where a word begins. */
5510 window_copy_cursor_previous_word_pos(struct window_mode_entry
*wme
,
5511 const char *separators
, u_int
*ppx
, u_int
*ppy
)
5513 struct window_copy_mode_data
*data
= wme
->data
;
5514 struct screen
*back_s
= data
->backing
;
5515 struct grid_reader gr
;
5516 u_int px
, py
, hsize
;
5519 hsize
= screen_hsize(back_s
);
5520 py
= hsize
+ data
->cy
- data
->oy
;
5522 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5523 grid_reader_cursor_previous_word(&gr
, separators
, 0, 1);
5524 grid_reader_get_cursor(&gr
, &px
, &py
);
5529 /* Move to the previous place where a word begins. */
5531 window_copy_cursor_previous_word(struct window_mode_entry
*wme
,
5532 const char *separators
, int already
)
5534 struct window_copy_mode_data
*data
= wme
->data
;
5535 struct window
*w
= wme
->wp
->window
;
5536 struct screen
*back_s
= data
->backing
;
5537 struct grid_reader gr
;
5538 u_int px
, py
, oldy
, hsize
;
5541 if (options_get_number(w
->options
, "mode-keys") == MODEKEY_EMACS
)
5547 hsize
= screen_hsize(back_s
);
5548 py
= hsize
+ data
->cy
- data
->oy
;
5551 grid_reader_start(&gr
, back_s
->grid
, px
, py
);
5552 grid_reader_cursor_previous_word(&gr
, separators
, already
, stop_at_eol
);
5553 grid_reader_get_cursor(&gr
, &px
, &py
);
5554 window_copy_acquire_cursor_up(wme
, hsize
, data
->oy
, oldy
, px
, py
);
5558 window_copy_cursor_prompt(struct window_mode_entry
*wme
, int direction
,
5561 struct window_copy_mode_data
*data
= wme
->data
;
5562 struct screen
*s
= data
->backing
;
5563 struct grid
*gd
= s
->grid
;
5565 u_int line
= gd
->hsize
- data
->oy
+ data
->cy
;
5569 line_flag
= GRID_LINE_START_OUTPUT
;
5571 line_flag
= GRID_LINE_START_PROMPT
;
5573 if (direction
== 0) { /* up */
5578 end_line
= gd
->hsize
+ gd
->sy
- 1;
5581 if (line
== end_line
)
5584 if (line
== end_line
)
5588 if (grid_get_line(gd
, line
)->flags
& line_flag
)
5593 if (line
> gd
->hsize
) {
5594 data
->cy
= line
- gd
->hsize
;
5598 data
->oy
= gd
->hsize
- line
;
5601 window_copy_update_selection(wme
, 1, 0);
5602 window_copy_redraw_screen(wme
);
5606 window_copy_scroll_up(struct window_mode_entry
*wme
, u_int ny
)
5608 struct window_pane
*wp
= wme
->wp
;
5609 struct window_copy_mode_data
*data
= wme
->data
;
5610 struct screen
*s
= &data
->screen
;
5611 struct screen_write_ctx ctx
;
5619 if (data
->searchmark
!= NULL
&& !data
->timeout
)
5620 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
5621 window_copy_update_selection(wme
, 0, 0);
5623 screen_write_start_pane(&ctx
, wp
, NULL
);
5624 screen_write_cursormove(&ctx
, 0, 0, 0);
5625 screen_write_deleteline(&ctx
, ny
, 8);
5626 window_copy_write_lines(wme
, &ctx
, screen_size_y(s
) - ny
, ny
);
5627 window_copy_write_line(wme
, &ctx
, 0);
5628 if (screen_size_y(s
) > 1)
5629 window_copy_write_line(wme
, &ctx
, 1);
5630 if (screen_size_y(s
) > 3)
5631 window_copy_write_line(wme
, &ctx
, screen_size_y(s
) - 2);
5632 if (s
->sel
!= NULL
&& screen_size_y(s
) > ny
)
5633 window_copy_write_line(wme
, &ctx
, screen_size_y(s
) - ny
- 1);
5634 screen_write_cursormove(&ctx
, data
->cx
, data
->cy
, 0);
5635 screen_write_stop(&ctx
);
5636 wp
->flags
|= PANE_REDRAWSCROLLBAR
;
5640 window_copy_scroll_down(struct window_mode_entry
*wme
, u_int ny
)
5642 struct window_pane
*wp
= wme
->wp
;
5643 struct window_copy_mode_data
*data
= wme
->data
;
5644 struct screen
*s
= &data
->screen
;
5645 struct screen_write_ctx ctx
;
5647 if (ny
> screen_hsize(data
->backing
))
5650 if (data
->oy
> screen_hsize(data
->backing
) - ny
)
5651 ny
= screen_hsize(data
->backing
) - data
->oy
;
5656 if (data
->searchmark
!= NULL
&& !data
->timeout
)
5657 window_copy_search_marks(wme
, NULL
, data
->searchregex
, 1);
5658 window_copy_update_selection(wme
, 0, 0);
5660 screen_write_start_pane(&ctx
, wp
, NULL
);
5661 screen_write_cursormove(&ctx
, 0, 0, 0);
5662 screen_write_insertline(&ctx
, ny
, 8);
5663 window_copy_write_lines(wme
, &ctx
, 0, ny
);
5664 if (s
->sel
!= NULL
&& screen_size_y(s
) > ny
)
5665 window_copy_write_line(wme
, &ctx
, ny
);
5666 else if (ny
== 1) /* nuke position */
5667 window_copy_write_line(wme
, &ctx
, 1);
5668 screen_write_cursormove(&ctx
, data
->cx
, data
->cy
, 0);
5669 screen_write_stop(&ctx
);
5670 wp
->flags
|= PANE_REDRAWSCROLLBAR
;
5674 window_copy_rectangle_set(struct window_mode_entry
*wme
, int rectflag
)
5676 struct window_copy_mode_data
*data
= wme
->data
;
5679 data
->rectflag
= rectflag
;
5681 py
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5682 px
= window_copy_find_length(wme
, py
);
5684 window_copy_update_cursor(wme
, px
, data
->cy
);
5686 window_copy_update_selection(wme
, 1, 0);
5687 window_copy_redraw_screen(wme
);
5691 window_copy_move_mouse(struct mouse_event
*m
)
5693 struct window_pane
*wp
;
5694 struct window_mode_entry
*wme
;
5697 wp
= cmd_mouse_pane(m
, NULL
, NULL
);
5700 wme
= TAILQ_FIRST(&wp
->modes
);
5703 if (wme
->mode
!= &window_copy_mode
&& wme
->mode
!= &window_view_mode
)
5706 if (cmd_mouse_at(wp
, m
, &x
, &y
, 0) != 0)
5709 window_copy_update_cursor(wme
, x
, y
);
5713 window_copy_start_drag(struct client
*c
, struct mouse_event
*m
)
5715 struct window_pane
*wp
;
5716 struct window_mode_entry
*wme
;
5717 struct window_copy_mode_data
*data
;
5723 wp
= cmd_mouse_pane(m
, NULL
, NULL
);
5726 wme
= TAILQ_FIRST(&wp
->modes
);
5729 if (wme
->mode
!= &window_copy_mode
&& wme
->mode
!= &window_view_mode
)
5732 if (cmd_mouse_at(wp
, m
, &x
, &y
, 1) != 0)
5735 c
->tty
.mouse_drag_update
= window_copy_drag_update
;
5736 c
->tty
.mouse_drag_release
= window_copy_drag_release
;
5739 yg
= screen_hsize(data
->backing
) + y
- data
->oy
;
5740 if (x
< data
->selrx
|| x
> data
->endselrx
|| yg
!= data
->selry
)
5741 data
->selflag
= SEL_CHAR
;
5742 switch (data
->selflag
) {
5744 if (data
->separators
!= NULL
) {
5745 window_copy_update_cursor(wme
, x
, y
);
5746 window_copy_cursor_previous_word_pos(wme
,
5747 data
->separators
, &x
, &y
);
5748 y
-= screen_hsize(data
->backing
) - data
->oy
;
5750 window_copy_update_cursor(wme
, x
, y
);
5753 window_copy_update_cursor(wme
, 0, y
);
5756 window_copy_update_cursor(wme
, x
, y
);
5757 window_copy_start_selection(wme
);
5761 window_copy_redraw_screen(wme
);
5762 window_copy_drag_update(c
, m
);
5766 window_copy_drag_update(struct client
*c
, struct mouse_event
*m
)
5768 struct window_pane
*wp
;
5769 struct window_mode_entry
*wme
;
5770 struct window_copy_mode_data
*data
;
5771 u_int x
, y
, old_cx
, old_cy
;
5772 struct timeval tv
= {
5773 .tv_usec
= WINDOW_COPY_DRAG_REPEAT_TIME
5779 wp
= cmd_mouse_pane(m
, NULL
, NULL
);
5782 wme
= TAILQ_FIRST(&wp
->modes
);
5785 if (wme
->mode
!= &window_copy_mode
&& wme
->mode
!= &window_view_mode
)
5789 evtimer_del(&data
->dragtimer
);
5791 if (cmd_mouse_at(wp
, m
, &x
, &y
, 0) != 0)
5796 window_copy_update_cursor(wme
, x
, y
);
5797 if (window_copy_update_selection(wme
, 1, 0))
5798 window_copy_redraw_selection(wme
, old_cy
);
5799 if (old_cy
!= data
->cy
|| old_cx
== data
->cx
) {
5801 evtimer_add(&data
->dragtimer
, &tv
);
5802 window_copy_cursor_up(wme
, 1);
5803 } else if (y
== screen_size_y(&data
->screen
) - 1) {
5804 evtimer_add(&data
->dragtimer
, &tv
);
5805 window_copy_cursor_down(wme
, 1);
5811 window_copy_drag_release(struct client
*c
, struct mouse_event
*m
)
5813 struct window_pane
*wp
;
5814 struct window_mode_entry
*wme
;
5815 struct window_copy_mode_data
*data
;
5820 wp
= cmd_mouse_pane(m
, NULL
, NULL
);
5823 wme
= TAILQ_FIRST(&wp
->modes
);
5826 if (wme
->mode
!= &window_copy_mode
&& wme
->mode
!= &window_view_mode
)
5830 evtimer_del(&data
->dragtimer
);
5834 window_copy_jump_to_mark(struct window_mode_entry
*wme
)
5836 struct window_copy_mode_data
*data
= wme
->data
;
5840 tmy
= screen_hsize(data
->backing
) + data
->cy
- data
->oy
;
5841 data
->cx
= data
->mx
;
5842 if (data
->my
< screen_hsize(data
->backing
)) {
5844 data
->oy
= screen_hsize(data
->backing
) - data
->my
;
5846 data
->cy
= data
->my
- screen_hsize(data
->backing
);
5852 window_copy_update_selection(wme
, 0, 0);
5853 window_copy_redraw_screen(wme
);
5856 /* Scroll up if the cursor went off the visible screen. */
5858 window_copy_acquire_cursor_up(struct window_mode_entry
*wme
, u_int hsize
,
5859 u_int oy
, u_int oldy
, u_int px
, u_int py
)
5861 u_int cy
, yy
, ny
, nd
;
5874 window_copy_cursor_up(wme
, 1);
5877 window_copy_update_cursor(wme
, px
, cy
);
5878 if (window_copy_update_selection(wme
, 1, 0))
5879 window_copy_redraw_lines(wme
, cy
, nd
);
5882 /* Scroll down if the cursor went off the visible screen. */
5884 window_copy_acquire_cursor_down(struct window_mode_entry
*wme
, u_int hsize
,
5885 u_int sy
, u_int oy
, u_int oldy
, u_int px
, u_int py
, int no_reset
)
5887 u_int cy
, yy
, ny
, nd
;
5889 cy
= py
- hsize
+ oy
;
5900 window_copy_cursor_down(wme
, 1);
5904 window_copy_update_cursor(wme
, px
, yy
);
5906 window_copy_update_cursor(wme
, px
, cy
);
5907 if (window_copy_update_selection(wme
, 1, no_reset
))
5908 window_copy_redraw_lines(wme
, oldy
, nd
);