1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek *
6eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek *
10eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek */
18eda6f593SDavid van Moolenbroek
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek
21*0a6a1f1dSLionel Sambuc #include <ctype.h>
22eda6f593SDavid van Moolenbroek #include <stdlib.h>
23eda6f593SDavid van Moolenbroek #include <string.h>
24eda6f593SDavid van Moolenbroek
25eda6f593SDavid van Moolenbroek #include "tmux.h"
26eda6f593SDavid van Moolenbroek
27eda6f593SDavid van Moolenbroek struct screen *window_copy_init(struct window_pane *);
28eda6f593SDavid van Moolenbroek void window_copy_free(struct window_pane *);
29eda6f593SDavid van Moolenbroek void window_copy_resize(struct window_pane *, u_int, u_int);
30eda6f593SDavid van Moolenbroek void window_copy_key(struct window_pane *, struct session *, int);
31eda6f593SDavid van Moolenbroek int window_copy_key_input(struct window_pane *, int);
32eda6f593SDavid van Moolenbroek int window_copy_key_numeric_prefix(struct window_pane *, int);
33eda6f593SDavid van Moolenbroek void window_copy_mouse(
34eda6f593SDavid van Moolenbroek struct window_pane *, struct session *, struct mouse_event *);
35eda6f593SDavid van Moolenbroek
36eda6f593SDavid van Moolenbroek void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
37eda6f593SDavid van Moolenbroek void window_copy_redraw_screen(struct window_pane *);
38eda6f593SDavid van Moolenbroek void window_copy_write_line(
39eda6f593SDavid van Moolenbroek struct window_pane *, struct screen_write_ctx *, u_int);
40eda6f593SDavid van Moolenbroek void window_copy_write_lines(
41eda6f593SDavid van Moolenbroek struct window_pane *, struct screen_write_ctx *, u_int, u_int);
42eda6f593SDavid van Moolenbroek
43eda6f593SDavid van Moolenbroek void window_copy_scroll_to(struct window_pane *, u_int, u_int);
44eda6f593SDavid van Moolenbroek int window_copy_search_compare(
45*0a6a1f1dSLionel Sambuc struct grid *, u_int, u_int, struct grid *, u_int, int);
46eda6f593SDavid van Moolenbroek int window_copy_search_lr(
47*0a6a1f1dSLionel Sambuc struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int);
48eda6f593SDavid van Moolenbroek int window_copy_search_rl(
49*0a6a1f1dSLionel Sambuc struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int);
50eda6f593SDavid van Moolenbroek void window_copy_search_up(struct window_pane *, const char *);
51eda6f593SDavid van Moolenbroek void window_copy_search_down(struct window_pane *, const char *);
52eda6f593SDavid van Moolenbroek void window_copy_goto_line(struct window_pane *, const char *);
53eda6f593SDavid van Moolenbroek void window_copy_update_cursor(struct window_pane *, u_int, u_int);
54eda6f593SDavid van Moolenbroek void window_copy_start_selection(struct window_pane *);
55*0a6a1f1dSLionel Sambuc int window_copy_update_selection(struct window_pane *, int);
56*0a6a1f1dSLionel Sambuc void *window_copy_get_selection(struct window_pane *, size_t *);
57*0a6a1f1dSLionel Sambuc void window_copy_copy_buffer(struct window_pane *, int, void *, size_t);
58*0a6a1f1dSLionel Sambuc void window_copy_copy_pipe(
59*0a6a1f1dSLionel Sambuc struct window_pane *, struct session *, int, const char *);
60*0a6a1f1dSLionel Sambuc void window_copy_copy_selection(struct window_pane *, int);
61eda6f593SDavid van Moolenbroek void window_copy_clear_selection(struct window_pane *);
62eda6f593SDavid van Moolenbroek void window_copy_copy_line(
63eda6f593SDavid van Moolenbroek struct window_pane *, char **, size_t *, u_int, u_int, u_int);
64eda6f593SDavid van Moolenbroek int window_copy_in_set(struct window_pane *, u_int, u_int, const char *);
65eda6f593SDavid van Moolenbroek u_int window_copy_find_length(struct window_pane *, u_int);
66eda6f593SDavid van Moolenbroek void window_copy_cursor_start_of_line(struct window_pane *);
67eda6f593SDavid van Moolenbroek void window_copy_cursor_back_to_indentation(struct window_pane *);
68eda6f593SDavid van Moolenbroek void window_copy_cursor_end_of_line(struct window_pane *);
69*0a6a1f1dSLionel Sambuc void window_copy_other_end(struct window_pane *);
70eda6f593SDavid van Moolenbroek void window_copy_cursor_left(struct window_pane *);
71eda6f593SDavid van Moolenbroek void window_copy_cursor_right(struct window_pane *);
72eda6f593SDavid van Moolenbroek void window_copy_cursor_up(struct window_pane *, int);
73eda6f593SDavid van Moolenbroek void window_copy_cursor_down(struct window_pane *, int);
74eda6f593SDavid van Moolenbroek void window_copy_cursor_jump(struct window_pane *);
75eda6f593SDavid van Moolenbroek void window_copy_cursor_jump_back(struct window_pane *);
76*0a6a1f1dSLionel Sambuc void window_copy_cursor_jump_to(struct window_pane *);
77*0a6a1f1dSLionel Sambuc void window_copy_cursor_jump_to_back(struct window_pane *);
78eda6f593SDavid van Moolenbroek void window_copy_cursor_next_word(struct window_pane *, const char *);
79eda6f593SDavid van Moolenbroek void window_copy_cursor_next_word_end(struct window_pane *, const char *);
80eda6f593SDavid van Moolenbroek void window_copy_cursor_previous_word(struct window_pane *, const char *);
81eda6f593SDavid van Moolenbroek void window_copy_scroll_up(struct window_pane *, u_int);
82eda6f593SDavid van Moolenbroek void window_copy_scroll_down(struct window_pane *, u_int);
83eda6f593SDavid van Moolenbroek void window_copy_rectangle_toggle(struct window_pane *);
84eda6f593SDavid van Moolenbroek
85eda6f593SDavid van Moolenbroek const struct window_mode window_copy_mode = {
86eda6f593SDavid van Moolenbroek window_copy_init,
87eda6f593SDavid van Moolenbroek window_copy_free,
88eda6f593SDavid van Moolenbroek window_copy_resize,
89eda6f593SDavid van Moolenbroek window_copy_key,
90eda6f593SDavid van Moolenbroek window_copy_mouse,
91eda6f593SDavid van Moolenbroek NULL,
92eda6f593SDavid van Moolenbroek };
93eda6f593SDavid van Moolenbroek
94eda6f593SDavid van Moolenbroek enum window_copy_input_type {
95eda6f593SDavid van Moolenbroek WINDOW_COPY_OFF,
96eda6f593SDavid van Moolenbroek WINDOW_COPY_NUMERICPREFIX,
97eda6f593SDavid van Moolenbroek WINDOW_COPY_SEARCHUP,
98eda6f593SDavid van Moolenbroek WINDOW_COPY_SEARCHDOWN,
99eda6f593SDavid van Moolenbroek WINDOW_COPY_JUMPFORWARD,
100eda6f593SDavid van Moolenbroek WINDOW_COPY_JUMPBACK,
101*0a6a1f1dSLionel Sambuc WINDOW_COPY_JUMPTOFORWARD,
102*0a6a1f1dSLionel Sambuc WINDOW_COPY_JUMPTOBACK,
103eda6f593SDavid van Moolenbroek WINDOW_COPY_GOTOLINE,
104eda6f593SDavid van Moolenbroek };
105eda6f593SDavid van Moolenbroek
106eda6f593SDavid van Moolenbroek /*
107eda6f593SDavid van Moolenbroek * Copy-mode's visible screen (the "screen" field) is filled from one of
108eda6f593SDavid van Moolenbroek * two sources: the original contents of the pane (used when we
109eda6f593SDavid van Moolenbroek * actually enter via the "copy-mode" command, to copy the contents of
110eda6f593SDavid van Moolenbroek * the current pane), or else a series of lines containing the output
111eda6f593SDavid van Moolenbroek * from an output-writing tmux command (such as any of the "show-*" or
112eda6f593SDavid van Moolenbroek * "list-*" commands).
113eda6f593SDavid van Moolenbroek *
114eda6f593SDavid van Moolenbroek * In either case, the full content of the copy-mode grid is pointed at
115eda6f593SDavid van Moolenbroek * by the "backing" field, and is copied into "screen" as needed (that
116eda6f593SDavid van Moolenbroek * is, when scrolling occurs). When copy-mode is backed by a pane,
117eda6f593SDavid van Moolenbroek * backing points directly at that pane's screen structure (&wp->base);
118eda6f593SDavid van Moolenbroek * when backed by a list of output-lines from a command, it points at
119eda6f593SDavid van Moolenbroek * a newly-allocated screen structure (which is deallocated when the
120eda6f593SDavid van Moolenbroek * mode ends).
121eda6f593SDavid van Moolenbroek */
122eda6f593SDavid van Moolenbroek struct window_copy_mode_data {
123eda6f593SDavid van Moolenbroek struct screen screen;
124eda6f593SDavid van Moolenbroek
125eda6f593SDavid van Moolenbroek struct screen *backing;
126eda6f593SDavid van Moolenbroek int backing_written; /* backing display has started */
127eda6f593SDavid van Moolenbroek
128eda6f593SDavid van Moolenbroek struct mode_key_data mdata;
129eda6f593SDavid van Moolenbroek
130eda6f593SDavid van Moolenbroek u_int oy;
131eda6f593SDavid van Moolenbroek
132eda6f593SDavid van Moolenbroek u_int selx;
133eda6f593SDavid van Moolenbroek u_int sely;
134eda6f593SDavid van Moolenbroek
135eda6f593SDavid van Moolenbroek u_int rectflag; /* are we in rectangle copy mode? */
136eda6f593SDavid van Moolenbroek
137eda6f593SDavid van Moolenbroek u_int cx;
138eda6f593SDavid van Moolenbroek u_int cy;
139eda6f593SDavid van Moolenbroek
140eda6f593SDavid van Moolenbroek u_int lastcx; /* position in last line with content */
141eda6f593SDavid van Moolenbroek u_int lastsx; /* size of last line with content */
142eda6f593SDavid van Moolenbroek
143eda6f593SDavid van Moolenbroek enum window_copy_input_type inputtype;
144eda6f593SDavid van Moolenbroek const char *inputprompt;
145eda6f593SDavid van Moolenbroek char *inputstr;
146eda6f593SDavid van Moolenbroek
147*0a6a1f1dSLionel Sambuc int numprefix;
148eda6f593SDavid van Moolenbroek
149eda6f593SDavid van Moolenbroek enum window_copy_input_type searchtype;
150eda6f593SDavid van Moolenbroek char *searchstr;
151eda6f593SDavid van Moolenbroek
152eda6f593SDavid van Moolenbroek enum window_copy_input_type jumptype;
153eda6f593SDavid van Moolenbroek char jumpchar;
154eda6f593SDavid van Moolenbroek };
155eda6f593SDavid van Moolenbroek
156eda6f593SDavid van Moolenbroek struct screen *
window_copy_init(struct window_pane * wp)157eda6f593SDavid van Moolenbroek window_copy_init(struct window_pane *wp)
158eda6f593SDavid van Moolenbroek {
159eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data;
160eda6f593SDavid van Moolenbroek struct screen *s;
161eda6f593SDavid van Moolenbroek int keys;
162eda6f593SDavid van Moolenbroek
163eda6f593SDavid van Moolenbroek wp->modedata = data = xmalloc(sizeof *data);
164eda6f593SDavid van Moolenbroek data->oy = 0;
165eda6f593SDavid van Moolenbroek data->cx = 0;
166eda6f593SDavid van Moolenbroek data->cy = 0;
167eda6f593SDavid van Moolenbroek
168eda6f593SDavid van Moolenbroek data->lastcx = 0;
169eda6f593SDavid van Moolenbroek data->lastsx = 0;
170eda6f593SDavid van Moolenbroek
171eda6f593SDavid van Moolenbroek data->backing_written = 0;
172eda6f593SDavid van Moolenbroek
173eda6f593SDavid van Moolenbroek data->rectflag = 0;
174eda6f593SDavid van Moolenbroek
175eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_OFF;
176eda6f593SDavid van Moolenbroek data->inputprompt = NULL;
177eda6f593SDavid van Moolenbroek data->inputstr = xstrdup("");
178*0a6a1f1dSLionel Sambuc data->numprefix = -1;
179eda6f593SDavid van Moolenbroek
180eda6f593SDavid van Moolenbroek data->searchtype = WINDOW_COPY_OFF;
181eda6f593SDavid van Moolenbroek data->searchstr = NULL;
182eda6f593SDavid van Moolenbroek
183eda6f593SDavid van Moolenbroek if (wp->fd != -1)
184eda6f593SDavid van Moolenbroek bufferevent_disable(wp->event, EV_READ|EV_WRITE);
185eda6f593SDavid van Moolenbroek
186eda6f593SDavid van Moolenbroek data->jumptype = WINDOW_COPY_OFF;
187eda6f593SDavid van Moolenbroek data->jumpchar = '\0';
188eda6f593SDavid van Moolenbroek
189eda6f593SDavid van Moolenbroek s = &data->screen;
190eda6f593SDavid van Moolenbroek screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
191eda6f593SDavid van Moolenbroek if (options_get_number(&wp->window->options, "mode-mouse"))
192eda6f593SDavid van Moolenbroek s->mode |= MODE_MOUSE_STANDARD;
193eda6f593SDavid van Moolenbroek
194eda6f593SDavid van Moolenbroek keys = options_get_number(&wp->window->options, "mode-keys");
195eda6f593SDavid van Moolenbroek if (keys == MODEKEY_EMACS)
196eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
197eda6f593SDavid van Moolenbroek else
198eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
199eda6f593SDavid van Moolenbroek
200eda6f593SDavid van Moolenbroek data->backing = NULL;
201eda6f593SDavid van Moolenbroek
202eda6f593SDavid van Moolenbroek return (s);
203eda6f593SDavid van Moolenbroek }
204eda6f593SDavid van Moolenbroek
205eda6f593SDavid van Moolenbroek void
window_copy_init_from_pane(struct window_pane * wp)206eda6f593SDavid van Moolenbroek window_copy_init_from_pane(struct window_pane *wp)
207eda6f593SDavid van Moolenbroek {
208eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
209eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
210eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
211eda6f593SDavid van Moolenbroek u_int i;
212eda6f593SDavid van Moolenbroek
213eda6f593SDavid van Moolenbroek if (wp->mode != &window_copy_mode)
214eda6f593SDavid van Moolenbroek fatalx("not in copy mode");
215eda6f593SDavid van Moolenbroek
216eda6f593SDavid van Moolenbroek data->backing = &wp->base;
217eda6f593SDavid van Moolenbroek data->cx = data->backing->cx;
218eda6f593SDavid van Moolenbroek data->cy = data->backing->cy;
219eda6f593SDavid van Moolenbroek
220eda6f593SDavid van Moolenbroek s->cx = data->cx;
221eda6f593SDavid van Moolenbroek s->cy = data->cy;
222eda6f593SDavid van Moolenbroek
223eda6f593SDavid van Moolenbroek screen_write_start(&ctx, NULL, s);
224eda6f593SDavid van Moolenbroek for (i = 0; i < screen_size_y(s); i++)
225eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, i);
226eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, data->cx, data->cy);
227eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
228eda6f593SDavid van Moolenbroek }
229eda6f593SDavid van Moolenbroek
230eda6f593SDavid van Moolenbroek void
window_copy_init_for_output(struct window_pane * wp)231eda6f593SDavid van Moolenbroek window_copy_init_for_output(struct window_pane *wp)
232eda6f593SDavid van Moolenbroek {
233eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
234eda6f593SDavid van Moolenbroek
235eda6f593SDavid van Moolenbroek data->backing = xmalloc(sizeof *data->backing);
236eda6f593SDavid van Moolenbroek screen_init(data->backing, screen_size_x(&wp->base),
237eda6f593SDavid van Moolenbroek screen_size_y(&wp->base), UINT_MAX);
238eda6f593SDavid van Moolenbroek data->backing->mode &= ~MODE_WRAP;
239eda6f593SDavid van Moolenbroek }
240eda6f593SDavid van Moolenbroek
241eda6f593SDavid van Moolenbroek void
window_copy_free(struct window_pane * wp)242eda6f593SDavid van Moolenbroek window_copy_free(struct window_pane *wp)
243eda6f593SDavid van Moolenbroek {
244eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
245eda6f593SDavid van Moolenbroek
246eda6f593SDavid van Moolenbroek if (wp->fd != -1)
247eda6f593SDavid van Moolenbroek bufferevent_enable(wp->event, EV_READ|EV_WRITE);
248eda6f593SDavid van Moolenbroek
249*0a6a1f1dSLionel Sambuc free(data->searchstr);
250*0a6a1f1dSLionel Sambuc free(data->inputstr);
251eda6f593SDavid van Moolenbroek
252eda6f593SDavid van Moolenbroek if (data->backing != &wp->base) {
253eda6f593SDavid van Moolenbroek screen_free(data->backing);
254*0a6a1f1dSLionel Sambuc free(data->backing);
255eda6f593SDavid van Moolenbroek }
256eda6f593SDavid van Moolenbroek screen_free(&data->screen);
257eda6f593SDavid van Moolenbroek
258*0a6a1f1dSLionel Sambuc free(data);
259eda6f593SDavid van Moolenbroek }
260eda6f593SDavid van Moolenbroek
261eda6f593SDavid van Moolenbroek void
window_copy_add(struct window_pane * wp,const char * fmt,...)262eda6f593SDavid van Moolenbroek window_copy_add(struct window_pane *wp, const char *fmt, ...)
263eda6f593SDavid van Moolenbroek {
264eda6f593SDavid van Moolenbroek va_list ap;
265eda6f593SDavid van Moolenbroek
266eda6f593SDavid van Moolenbroek va_start(ap, fmt);
267eda6f593SDavid van Moolenbroek window_copy_vadd(wp, fmt, ap);
268eda6f593SDavid van Moolenbroek va_end(ap);
269eda6f593SDavid van Moolenbroek }
270eda6f593SDavid van Moolenbroek
271eda6f593SDavid van Moolenbroek void
window_copy_vadd(struct window_pane * wp,const char * fmt,va_list ap)272eda6f593SDavid van Moolenbroek window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
273eda6f593SDavid van Moolenbroek {
274eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
275eda6f593SDavid van Moolenbroek struct screen *backing = data->backing;
276eda6f593SDavid van Moolenbroek struct screen_write_ctx back_ctx, ctx;
277eda6f593SDavid van Moolenbroek struct grid_cell gc;
278eda6f593SDavid van Moolenbroek int utf8flag;
279eda6f593SDavid van Moolenbroek u_int old_hsize;
280eda6f593SDavid van Moolenbroek
281eda6f593SDavid van Moolenbroek if (backing == &wp->base)
282eda6f593SDavid van Moolenbroek return;
283eda6f593SDavid van Moolenbroek
284eda6f593SDavid van Moolenbroek utf8flag = options_get_number(&wp->window->options, "utf8");
285eda6f593SDavid van Moolenbroek memcpy(&gc, &grid_default_cell, sizeof gc);
286eda6f593SDavid van Moolenbroek
287eda6f593SDavid van Moolenbroek old_hsize = screen_hsize(data->backing);
288eda6f593SDavid van Moolenbroek screen_write_start(&back_ctx, NULL, backing);
289eda6f593SDavid van Moolenbroek if (data->backing_written) {
290eda6f593SDavid van Moolenbroek /*
291eda6f593SDavid van Moolenbroek * On the second or later line, do a CRLF before writing
292eda6f593SDavid van Moolenbroek * (so it's on a new line).
293eda6f593SDavid van Moolenbroek */
294eda6f593SDavid van Moolenbroek screen_write_carriagereturn(&back_ctx);
295eda6f593SDavid van Moolenbroek screen_write_linefeed(&back_ctx, 0);
296eda6f593SDavid van Moolenbroek } else
297eda6f593SDavid van Moolenbroek data->backing_written = 1;
298eda6f593SDavid van Moolenbroek screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
299eda6f593SDavid van Moolenbroek screen_write_stop(&back_ctx);
300eda6f593SDavid van Moolenbroek
301eda6f593SDavid van Moolenbroek data->oy += screen_hsize(data->backing) - old_hsize;
302eda6f593SDavid van Moolenbroek
303eda6f593SDavid van Moolenbroek screen_write_start(&ctx, wp, &data->screen);
304eda6f593SDavid van Moolenbroek
305eda6f593SDavid van Moolenbroek /*
306eda6f593SDavid van Moolenbroek * If the history has changed, draw the top line.
307eda6f593SDavid van Moolenbroek * (If there's any history at all, it has changed.)
308eda6f593SDavid van Moolenbroek */
309eda6f593SDavid van Moolenbroek if (screen_hsize(data->backing))
310eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, 0, 1);
311eda6f593SDavid van Moolenbroek
312eda6f593SDavid van Moolenbroek /* Write the line, if it's visible. */
313eda6f593SDavid van Moolenbroek if (backing->cy + data->oy < screen_size_y(backing))
314eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, backing->cy, 1);
315eda6f593SDavid van Moolenbroek
316eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
317eda6f593SDavid van Moolenbroek }
318eda6f593SDavid van Moolenbroek
319eda6f593SDavid van Moolenbroek void
window_copy_pageup(struct window_pane * wp)320eda6f593SDavid van Moolenbroek window_copy_pageup(struct window_pane *wp)
321eda6f593SDavid van Moolenbroek {
322eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
323eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
324eda6f593SDavid van Moolenbroek u_int n;
325eda6f593SDavid van Moolenbroek
326eda6f593SDavid van Moolenbroek n = 1;
327eda6f593SDavid van Moolenbroek if (screen_size_y(s) > 2)
328eda6f593SDavid van Moolenbroek n = screen_size_y(s) - 2;
329eda6f593SDavid van Moolenbroek if (data->oy + n > screen_hsize(data->backing))
330eda6f593SDavid van Moolenbroek data->oy = screen_hsize(data->backing);
331eda6f593SDavid van Moolenbroek else
332eda6f593SDavid van Moolenbroek data->oy += n;
333*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
334eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
335eda6f593SDavid van Moolenbroek }
336eda6f593SDavid van Moolenbroek
337eda6f593SDavid van Moolenbroek void
window_copy_resize(struct window_pane * wp,u_int sx,u_int sy)338eda6f593SDavid van Moolenbroek window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
339eda6f593SDavid van Moolenbroek {
340eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
341eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
342eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
343eda6f593SDavid van Moolenbroek
344*0a6a1f1dSLionel Sambuc screen_resize(s, sx, sy, 0);
345eda6f593SDavid van Moolenbroek if (data->backing != &wp->base)
346*0a6a1f1dSLionel Sambuc screen_resize(data->backing, sx, sy, 0);
347eda6f593SDavid van Moolenbroek
348eda6f593SDavid van Moolenbroek if (data->cy > sy - 1)
349eda6f593SDavid van Moolenbroek data->cy = sy - 1;
350eda6f593SDavid van Moolenbroek if (data->cx > sx)
351eda6f593SDavid van Moolenbroek data->cx = sx;
352eda6f593SDavid van Moolenbroek if (data->oy > screen_hsize(data->backing))
353eda6f593SDavid van Moolenbroek data->oy = screen_hsize(data->backing);
354eda6f593SDavid van Moolenbroek
355eda6f593SDavid van Moolenbroek window_copy_clear_selection(wp);
356eda6f593SDavid van Moolenbroek
357eda6f593SDavid van Moolenbroek screen_write_start(&ctx, NULL, s);
358eda6f593SDavid van Moolenbroek window_copy_write_lines(wp, &ctx, 0, screen_size_y(s) - 1);
359eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
360eda6f593SDavid van Moolenbroek
361eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
362eda6f593SDavid van Moolenbroek }
363eda6f593SDavid van Moolenbroek
364eda6f593SDavid van Moolenbroek void
window_copy_key(struct window_pane * wp,struct session * sess,int key)365eda6f593SDavid van Moolenbroek window_copy_key(struct window_pane *wp, struct session *sess, int key)
366eda6f593SDavid van Moolenbroek {
367eda6f593SDavid van Moolenbroek const char *word_separators;
368eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
369eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
370*0a6a1f1dSLionel Sambuc u_int n;
371*0a6a1f1dSLionel Sambuc int np, keys;
372eda6f593SDavid van Moolenbroek enum mode_key_cmd cmd;
373*0a6a1f1dSLionel Sambuc const char *arg;
374eda6f593SDavid van Moolenbroek
375eda6f593SDavid van Moolenbroek np = data->numprefix;
376*0a6a1f1dSLionel Sambuc if (np <= 0)
377eda6f593SDavid van Moolenbroek np = 1;
378eda6f593SDavid van Moolenbroek
379eda6f593SDavid van Moolenbroek if (data->inputtype == WINDOW_COPY_JUMPFORWARD ||
380*0a6a1f1dSLionel Sambuc data->inputtype == WINDOW_COPY_JUMPBACK ||
381*0a6a1f1dSLionel Sambuc data->inputtype == WINDOW_COPY_JUMPTOFORWARD ||
382*0a6a1f1dSLionel Sambuc data->inputtype == WINDOW_COPY_JUMPTOBACK) {
383eda6f593SDavid van Moolenbroek /* Ignore keys with modifiers. */
384eda6f593SDavid van Moolenbroek if ((key & KEYC_MASK_MOD) == 0) {
385eda6f593SDavid van Moolenbroek data->jumpchar = key;
386eda6f593SDavid van Moolenbroek if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
387eda6f593SDavid van Moolenbroek for (; np != 0; np--)
388eda6f593SDavid van Moolenbroek window_copy_cursor_jump(wp);
389*0a6a1f1dSLionel Sambuc } else if (data->inputtype == WINDOW_COPY_JUMPBACK) {
390eda6f593SDavid van Moolenbroek for (; np != 0; np--)
391eda6f593SDavid van Moolenbroek window_copy_cursor_jump_back(wp);
392*0a6a1f1dSLionel Sambuc } else if (data->inputtype == WINDOW_COPY_JUMPTOFORWARD) {
393*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
394*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to(wp);
395*0a6a1f1dSLionel Sambuc } else if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
396*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
397*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to_back(wp);
398eda6f593SDavid van Moolenbroek }
399eda6f593SDavid van Moolenbroek }
400eda6f593SDavid van Moolenbroek data->jumptype = data->inputtype;
401eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_OFF;
402eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
403eda6f593SDavid van Moolenbroek return;
404eda6f593SDavid van Moolenbroek } else if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
405eda6f593SDavid van Moolenbroek if (window_copy_key_numeric_prefix(wp, key) == 0)
406eda6f593SDavid van Moolenbroek return;
407eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_OFF;
408eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
409eda6f593SDavid van Moolenbroek } else if (data->inputtype != WINDOW_COPY_OFF) {
410eda6f593SDavid van Moolenbroek if (window_copy_key_input(wp, key) != 0)
411eda6f593SDavid van Moolenbroek goto input_off;
412eda6f593SDavid van Moolenbroek return;
413eda6f593SDavid van Moolenbroek }
414eda6f593SDavid van Moolenbroek
415*0a6a1f1dSLionel Sambuc cmd = mode_key_lookup(&data->mdata, key, &arg);
416eda6f593SDavid van Moolenbroek switch (cmd) {
417eda6f593SDavid van Moolenbroek case MODEKEYCOPY_CANCEL:
418eda6f593SDavid van Moolenbroek window_pane_reset_mode(wp);
419eda6f593SDavid van Moolenbroek return;
420*0a6a1f1dSLionel Sambuc case MODEKEYCOPY_OTHEREND:
421*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
422*0a6a1f1dSLionel Sambuc window_copy_other_end(wp);
423*0a6a1f1dSLionel Sambuc break;
424eda6f593SDavid van Moolenbroek case MODEKEYCOPY_LEFT:
425eda6f593SDavid van Moolenbroek for (; np != 0; np--)
426eda6f593SDavid van Moolenbroek window_copy_cursor_left(wp);
427eda6f593SDavid van Moolenbroek break;
428eda6f593SDavid van Moolenbroek case MODEKEYCOPY_RIGHT:
429eda6f593SDavid van Moolenbroek for (; np != 0; np--)
430eda6f593SDavid van Moolenbroek window_copy_cursor_right(wp);
431eda6f593SDavid van Moolenbroek break;
432eda6f593SDavid van Moolenbroek case MODEKEYCOPY_UP:
433eda6f593SDavid van Moolenbroek for (; np != 0; np--)
434eda6f593SDavid van Moolenbroek window_copy_cursor_up(wp, 0);
435eda6f593SDavid van Moolenbroek break;
436eda6f593SDavid van Moolenbroek case MODEKEYCOPY_DOWN:
437eda6f593SDavid van Moolenbroek for (; np != 0; np--)
438eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
439eda6f593SDavid van Moolenbroek break;
440eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SCROLLUP:
441eda6f593SDavid van Moolenbroek for (; np != 0; np--)
442eda6f593SDavid van Moolenbroek window_copy_cursor_up(wp, 1);
443eda6f593SDavid van Moolenbroek break;
444eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SCROLLDOWN:
445eda6f593SDavid van Moolenbroek for (; np != 0; np--)
446eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 1);
447eda6f593SDavid van Moolenbroek break;
448eda6f593SDavid van Moolenbroek case MODEKEYCOPY_PREVIOUSPAGE:
449eda6f593SDavid van Moolenbroek for (; np != 0; np--)
450eda6f593SDavid van Moolenbroek window_copy_pageup(wp);
451eda6f593SDavid van Moolenbroek break;
452eda6f593SDavid van Moolenbroek case MODEKEYCOPY_NEXTPAGE:
453eda6f593SDavid van Moolenbroek n = 1;
454eda6f593SDavid van Moolenbroek if (screen_size_y(s) > 2)
455eda6f593SDavid van Moolenbroek n = screen_size_y(s) - 2;
456eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
457eda6f593SDavid van Moolenbroek if (data->oy < n)
458eda6f593SDavid van Moolenbroek data->oy = 0;
459eda6f593SDavid van Moolenbroek else
460eda6f593SDavid van Moolenbroek data->oy -= n;
461eda6f593SDavid van Moolenbroek }
462*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
463eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
464eda6f593SDavid van Moolenbroek break;
465eda6f593SDavid van Moolenbroek case MODEKEYCOPY_HALFPAGEUP:
466eda6f593SDavid van Moolenbroek n = screen_size_y(s) / 2;
467eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
468eda6f593SDavid van Moolenbroek if (data->oy + n > screen_hsize(data->backing))
469eda6f593SDavid van Moolenbroek data->oy = screen_hsize(data->backing);
470eda6f593SDavid van Moolenbroek else
471eda6f593SDavid van Moolenbroek data->oy += n;
472eda6f593SDavid van Moolenbroek }
473*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
474eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
475eda6f593SDavid van Moolenbroek break;
476eda6f593SDavid van Moolenbroek case MODEKEYCOPY_HALFPAGEDOWN:
477eda6f593SDavid van Moolenbroek n = screen_size_y(s) / 2;
478eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
479eda6f593SDavid van Moolenbroek if (data->oy < n)
480eda6f593SDavid van Moolenbroek data->oy = 0;
481eda6f593SDavid van Moolenbroek else
482eda6f593SDavid van Moolenbroek data->oy -= n;
483eda6f593SDavid van Moolenbroek }
484*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
485eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
486eda6f593SDavid van Moolenbroek break;
487eda6f593SDavid van Moolenbroek case MODEKEYCOPY_TOPLINE:
488eda6f593SDavid van Moolenbroek data->cx = 0;
489eda6f593SDavid van Moolenbroek data->cy = 0;
490*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
491eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
492eda6f593SDavid van Moolenbroek break;
493eda6f593SDavid van Moolenbroek case MODEKEYCOPY_MIDDLELINE:
494eda6f593SDavid van Moolenbroek data->cx = 0;
495eda6f593SDavid van Moolenbroek data->cy = (screen_size_y(s) - 1) / 2;
496*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
497eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
498eda6f593SDavid van Moolenbroek break;
499eda6f593SDavid van Moolenbroek case MODEKEYCOPY_BOTTOMLINE:
500eda6f593SDavid van Moolenbroek data->cx = 0;
501eda6f593SDavid van Moolenbroek data->cy = screen_size_y(s) - 1;
502*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
503eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
504eda6f593SDavid van Moolenbroek break;
505eda6f593SDavid van Moolenbroek case MODEKEYCOPY_HISTORYTOP:
506eda6f593SDavid van Moolenbroek data->cx = 0;
507eda6f593SDavid van Moolenbroek data->cy = 0;
508eda6f593SDavid van Moolenbroek data->oy = screen_hsize(data->backing);
509*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
510eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
511eda6f593SDavid van Moolenbroek break;
512eda6f593SDavid van Moolenbroek case MODEKEYCOPY_HISTORYBOTTOM:
513eda6f593SDavid van Moolenbroek data->cx = 0;
514eda6f593SDavid van Moolenbroek data->cy = screen_size_y(s) - 1;
515eda6f593SDavid van Moolenbroek data->oy = 0;
516*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
517eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
518eda6f593SDavid van Moolenbroek break;
519eda6f593SDavid van Moolenbroek case MODEKEYCOPY_STARTSELECTION:
520eda6f593SDavid van Moolenbroek window_copy_start_selection(wp);
521eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
522eda6f593SDavid van Moolenbroek break;
523eda6f593SDavid van Moolenbroek case MODEKEYCOPY_COPYLINE:
524eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SELECTLINE:
525eda6f593SDavid van Moolenbroek window_copy_cursor_start_of_line(wp);
526eda6f593SDavid van Moolenbroek /* FALLTHROUGH */
527eda6f593SDavid van Moolenbroek case MODEKEYCOPY_COPYENDOFLINE:
528eda6f593SDavid van Moolenbroek window_copy_start_selection(wp);
529eda6f593SDavid van Moolenbroek for (; np > 1; np--)
530eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
531eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(wp);
532eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
533eda6f593SDavid van Moolenbroek
534eda6f593SDavid van Moolenbroek /* If a copy command then copy the selection and exit. */
535eda6f593SDavid van Moolenbroek if (sess != NULL &&
536eda6f593SDavid van Moolenbroek (cmd == MODEKEYCOPY_COPYLINE ||
537eda6f593SDavid van Moolenbroek cmd == MODEKEYCOPY_COPYENDOFLINE)) {
538*0a6a1f1dSLionel Sambuc window_copy_copy_selection(wp, -1);
539eda6f593SDavid van Moolenbroek window_pane_reset_mode(wp);
540eda6f593SDavid van Moolenbroek return;
541eda6f593SDavid van Moolenbroek }
542eda6f593SDavid van Moolenbroek break;
543eda6f593SDavid van Moolenbroek case MODEKEYCOPY_CLEARSELECTION:
544eda6f593SDavid van Moolenbroek window_copy_clear_selection(wp);
545eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
546eda6f593SDavid van Moolenbroek break;
547*0a6a1f1dSLionel Sambuc case MODEKEYCOPY_COPYPIPE:
548*0a6a1f1dSLionel Sambuc if (sess != NULL) {
549*0a6a1f1dSLionel Sambuc window_copy_copy_pipe(wp, sess, data->numprefix, arg);
550*0a6a1f1dSLionel Sambuc window_pane_reset_mode(wp);
551*0a6a1f1dSLionel Sambuc return;
552*0a6a1f1dSLionel Sambuc }
553*0a6a1f1dSLionel Sambuc break;
554eda6f593SDavid van Moolenbroek case MODEKEYCOPY_COPYSELECTION:
555eda6f593SDavid van Moolenbroek if (sess != NULL) {
556*0a6a1f1dSLionel Sambuc window_copy_copy_selection(wp, data->numprefix);
557eda6f593SDavid van Moolenbroek window_pane_reset_mode(wp);
558eda6f593SDavid van Moolenbroek return;
559eda6f593SDavid van Moolenbroek }
560eda6f593SDavid van Moolenbroek break;
561eda6f593SDavid van Moolenbroek case MODEKEYCOPY_STARTOFLINE:
562eda6f593SDavid van Moolenbroek window_copy_cursor_start_of_line(wp);
563eda6f593SDavid van Moolenbroek break;
564eda6f593SDavid van Moolenbroek case MODEKEYCOPY_BACKTOINDENTATION:
565eda6f593SDavid van Moolenbroek window_copy_cursor_back_to_indentation(wp);
566eda6f593SDavid van Moolenbroek break;
567eda6f593SDavid van Moolenbroek case MODEKEYCOPY_ENDOFLINE:
568eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(wp);
569eda6f593SDavid van Moolenbroek break;
570eda6f593SDavid van Moolenbroek case MODEKEYCOPY_NEXTSPACE:
571eda6f593SDavid van Moolenbroek for (; np != 0; np--)
572eda6f593SDavid van Moolenbroek window_copy_cursor_next_word(wp, " ");
573eda6f593SDavid van Moolenbroek break;
574eda6f593SDavid van Moolenbroek case MODEKEYCOPY_NEXTSPACEEND:
575eda6f593SDavid van Moolenbroek for (; np != 0; np--)
576eda6f593SDavid van Moolenbroek window_copy_cursor_next_word_end(wp, " ");
577eda6f593SDavid van Moolenbroek break;
578eda6f593SDavid van Moolenbroek case MODEKEYCOPY_NEXTWORD:
579eda6f593SDavid van Moolenbroek word_separators =
580*0a6a1f1dSLionel Sambuc options_get_string(&sess->options, "word-separators");
581eda6f593SDavid van Moolenbroek for (; np != 0; np--)
582eda6f593SDavid van Moolenbroek window_copy_cursor_next_word(wp, word_separators);
583eda6f593SDavid van Moolenbroek break;
584eda6f593SDavid van Moolenbroek case MODEKEYCOPY_NEXTWORDEND:
585eda6f593SDavid van Moolenbroek word_separators =
586*0a6a1f1dSLionel Sambuc options_get_string(&sess->options, "word-separators");
587eda6f593SDavid van Moolenbroek for (; np != 0; np--)
588eda6f593SDavid van Moolenbroek window_copy_cursor_next_word_end(wp, word_separators);
589eda6f593SDavid van Moolenbroek break;
590eda6f593SDavid van Moolenbroek case MODEKEYCOPY_PREVIOUSSPACE:
591eda6f593SDavid van Moolenbroek for (; np != 0; np--)
592eda6f593SDavid van Moolenbroek window_copy_cursor_previous_word(wp, " ");
593eda6f593SDavid van Moolenbroek break;
594eda6f593SDavid van Moolenbroek case MODEKEYCOPY_PREVIOUSWORD:
595eda6f593SDavid van Moolenbroek word_separators =
596*0a6a1f1dSLionel Sambuc options_get_string(&sess->options, "word-separators");
597eda6f593SDavid van Moolenbroek for (; np != 0; np--)
598eda6f593SDavid van Moolenbroek window_copy_cursor_previous_word(wp, word_separators);
599eda6f593SDavid van Moolenbroek break;
600eda6f593SDavid van Moolenbroek case MODEKEYCOPY_JUMP:
601eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_JUMPFORWARD;
602eda6f593SDavid van Moolenbroek data->inputprompt = "Jump Forward";
603eda6f593SDavid van Moolenbroek *data->inputstr = '\0';
604eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
605eda6f593SDavid van Moolenbroek return; /* skip numprefix reset */
606eda6f593SDavid van Moolenbroek case MODEKEYCOPY_JUMPAGAIN:
607eda6f593SDavid van Moolenbroek if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
608eda6f593SDavid van Moolenbroek for (; np != 0; np--)
609eda6f593SDavid van Moolenbroek window_copy_cursor_jump(wp);
610eda6f593SDavid van Moolenbroek } else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
611eda6f593SDavid van Moolenbroek for (; np != 0; np--)
612eda6f593SDavid van Moolenbroek window_copy_cursor_jump_back(wp);
613*0a6a1f1dSLionel Sambuc } else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
614*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
615*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to(wp);
616*0a6a1f1dSLionel Sambuc } else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
617*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
618*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to_back(wp);
619eda6f593SDavid van Moolenbroek }
620eda6f593SDavid van Moolenbroek break;
621eda6f593SDavid van Moolenbroek case MODEKEYCOPY_JUMPREVERSE:
622eda6f593SDavid van Moolenbroek if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
623eda6f593SDavid van Moolenbroek for (; np != 0; np--)
624eda6f593SDavid van Moolenbroek window_copy_cursor_jump_back(wp);
625eda6f593SDavid van Moolenbroek } else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
626eda6f593SDavid van Moolenbroek for (; np != 0; np--)
627eda6f593SDavid van Moolenbroek window_copy_cursor_jump(wp);
628*0a6a1f1dSLionel Sambuc } else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
629*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
630*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to_back(wp);
631*0a6a1f1dSLionel Sambuc } else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
632*0a6a1f1dSLionel Sambuc for (; np != 0; np--)
633*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to(wp);
634eda6f593SDavid van Moolenbroek }
635eda6f593SDavid van Moolenbroek break;
636eda6f593SDavid van Moolenbroek case MODEKEYCOPY_JUMPBACK:
637eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_JUMPBACK;
638eda6f593SDavid van Moolenbroek data->inputprompt = "Jump Back";
639eda6f593SDavid van Moolenbroek *data->inputstr = '\0';
640eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
641eda6f593SDavid van Moolenbroek return; /* skip numprefix reset */
642*0a6a1f1dSLionel Sambuc case MODEKEYCOPY_JUMPTO:
643*0a6a1f1dSLionel Sambuc data->inputtype = WINDOW_COPY_JUMPTOFORWARD;
644*0a6a1f1dSLionel Sambuc data->inputprompt = "Jump To";
645*0a6a1f1dSLionel Sambuc *data->inputstr = '\0';
646*0a6a1f1dSLionel Sambuc window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
647*0a6a1f1dSLionel Sambuc return; /* skip numprefix reset */
648*0a6a1f1dSLionel Sambuc case MODEKEYCOPY_JUMPTOBACK:
649*0a6a1f1dSLionel Sambuc data->inputtype = WINDOW_COPY_JUMPTOBACK;
650*0a6a1f1dSLionel Sambuc data->inputprompt = "Jump To Back";
651*0a6a1f1dSLionel Sambuc *data->inputstr = '\0';
652*0a6a1f1dSLionel Sambuc window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
653*0a6a1f1dSLionel Sambuc return; /* skip numprefix reset */
654eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SEARCHUP:
655eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_SEARCHUP;
656eda6f593SDavid van Moolenbroek data->inputprompt = "Search Up";
657eda6f593SDavid van Moolenbroek goto input_on;
658eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SEARCHDOWN:
659eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_SEARCHDOWN;
660eda6f593SDavid van Moolenbroek data->inputprompt = "Search Down";
661eda6f593SDavid van Moolenbroek goto input_on;
662eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SEARCHAGAIN:
663eda6f593SDavid van Moolenbroek case MODEKEYCOPY_SEARCHREVERSE:
664eda6f593SDavid van Moolenbroek switch (data->searchtype) {
665eda6f593SDavid van Moolenbroek case WINDOW_COPY_OFF:
666eda6f593SDavid van Moolenbroek case WINDOW_COPY_GOTOLINE:
667eda6f593SDavid van Moolenbroek case WINDOW_COPY_JUMPFORWARD:
668eda6f593SDavid van Moolenbroek case WINDOW_COPY_JUMPBACK:
669*0a6a1f1dSLionel Sambuc case WINDOW_COPY_JUMPTOFORWARD:
670*0a6a1f1dSLionel Sambuc case WINDOW_COPY_JUMPTOBACK:
671eda6f593SDavid van Moolenbroek case WINDOW_COPY_NUMERICPREFIX:
672eda6f593SDavid van Moolenbroek break;
673eda6f593SDavid van Moolenbroek case WINDOW_COPY_SEARCHUP:
674eda6f593SDavid van Moolenbroek if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
675eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
676eda6f593SDavid van Moolenbroek window_copy_search_up(
677eda6f593SDavid van Moolenbroek wp, data->searchstr);
678eda6f593SDavid van Moolenbroek }
679eda6f593SDavid van Moolenbroek } else {
680eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
681eda6f593SDavid van Moolenbroek window_copy_search_down(
682eda6f593SDavid van Moolenbroek wp, data->searchstr);
683eda6f593SDavid van Moolenbroek }
684eda6f593SDavid van Moolenbroek }
685eda6f593SDavid van Moolenbroek break;
686eda6f593SDavid van Moolenbroek case WINDOW_COPY_SEARCHDOWN:
687eda6f593SDavid van Moolenbroek if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
688eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
689eda6f593SDavid van Moolenbroek window_copy_search_down(
690eda6f593SDavid van Moolenbroek wp, data->searchstr);
691eda6f593SDavid van Moolenbroek }
692eda6f593SDavid van Moolenbroek } else {
693eda6f593SDavid van Moolenbroek for (; np != 0; np--) {
694eda6f593SDavid van Moolenbroek window_copy_search_up(
695eda6f593SDavid van Moolenbroek wp, data->searchstr);
696eda6f593SDavid van Moolenbroek }
697eda6f593SDavid van Moolenbroek }
698eda6f593SDavid van Moolenbroek break;
699eda6f593SDavid van Moolenbroek }
700eda6f593SDavid van Moolenbroek break;
701eda6f593SDavid van Moolenbroek case MODEKEYCOPY_GOTOLINE:
702eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_GOTOLINE;
703eda6f593SDavid van Moolenbroek data->inputprompt = "Goto Line";
704eda6f593SDavid van Moolenbroek *data->inputstr = '\0';
705eda6f593SDavid van Moolenbroek goto input_on;
706eda6f593SDavid van Moolenbroek case MODEKEYCOPY_STARTNUMBERPREFIX:
707eda6f593SDavid van Moolenbroek key &= KEYC_MASK_KEY;
708eda6f593SDavid van Moolenbroek if (key >= '0' && key <= '9') {
709eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_NUMERICPREFIX;
710eda6f593SDavid van Moolenbroek data->numprefix = 0;
711eda6f593SDavid van Moolenbroek window_copy_key_numeric_prefix(wp, key);
712eda6f593SDavid van Moolenbroek return;
713eda6f593SDavid van Moolenbroek }
714eda6f593SDavid van Moolenbroek break;
715eda6f593SDavid van Moolenbroek case MODEKEYCOPY_RECTANGLETOGGLE:
716eda6f593SDavid van Moolenbroek window_copy_rectangle_toggle(wp);
717eda6f593SDavid van Moolenbroek break;
718eda6f593SDavid van Moolenbroek default:
719eda6f593SDavid van Moolenbroek break;
720eda6f593SDavid van Moolenbroek }
721eda6f593SDavid van Moolenbroek
722*0a6a1f1dSLionel Sambuc data->numprefix = -1;
723eda6f593SDavid van Moolenbroek return;
724eda6f593SDavid van Moolenbroek
725eda6f593SDavid van Moolenbroek input_on:
726eda6f593SDavid van Moolenbroek keys = options_get_number(&wp->window->options, "mode-keys");
727eda6f593SDavid van Moolenbroek if (keys == MODEKEY_EMACS)
728eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_emacs_edit);
729eda6f593SDavid van Moolenbroek else
730eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_vi_edit);
731eda6f593SDavid van Moolenbroek
732eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
733eda6f593SDavid van Moolenbroek return;
734eda6f593SDavid van Moolenbroek
735eda6f593SDavid van Moolenbroek input_off:
736eda6f593SDavid van Moolenbroek keys = options_get_number(&wp->window->options, "mode-keys");
737eda6f593SDavid van Moolenbroek if (keys == MODEKEY_EMACS)
738eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
739eda6f593SDavid van Moolenbroek else
740eda6f593SDavid van Moolenbroek mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
741eda6f593SDavid van Moolenbroek
742eda6f593SDavid van Moolenbroek data->inputtype = WINDOW_COPY_OFF;
743eda6f593SDavid van Moolenbroek data->inputprompt = NULL;
744eda6f593SDavid van Moolenbroek
745eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
746eda6f593SDavid van Moolenbroek }
747eda6f593SDavid van Moolenbroek
748eda6f593SDavid van Moolenbroek int
window_copy_key_input(struct window_pane * wp,int key)749eda6f593SDavid van Moolenbroek window_copy_key_input(struct window_pane *wp, int key)
750eda6f593SDavid van Moolenbroek {
751eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
752eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
753*0a6a1f1dSLionel Sambuc size_t inputlen, n;
754*0a6a1f1dSLionel Sambuc int np;
755*0a6a1f1dSLionel Sambuc struct paste_buffer *pb;
756*0a6a1f1dSLionel Sambuc u_char ch;
757eda6f593SDavid van Moolenbroek
758*0a6a1f1dSLionel Sambuc switch (mode_key_lookup(&data->mdata, key, NULL)) {
759eda6f593SDavid van Moolenbroek case MODEKEYEDIT_CANCEL:
760*0a6a1f1dSLionel Sambuc data->numprefix = -1;
761eda6f593SDavid van Moolenbroek return (-1);
762eda6f593SDavid van Moolenbroek case MODEKEYEDIT_BACKSPACE:
763eda6f593SDavid van Moolenbroek inputlen = strlen(data->inputstr);
764eda6f593SDavid van Moolenbroek if (inputlen > 0)
765eda6f593SDavid van Moolenbroek data->inputstr[inputlen - 1] = '\0';
766eda6f593SDavid van Moolenbroek break;
767eda6f593SDavid van Moolenbroek case MODEKEYEDIT_DELETELINE:
768eda6f593SDavid van Moolenbroek *data->inputstr = '\0';
769eda6f593SDavid van Moolenbroek break;
770*0a6a1f1dSLionel Sambuc case MODEKEYEDIT_PASTE:
771*0a6a1f1dSLionel Sambuc if ((pb = paste_get_top(&global_buffers)) == NULL)
772*0a6a1f1dSLionel Sambuc break;
773*0a6a1f1dSLionel Sambuc for (n = 0; n < pb->size; n++) {
774*0a6a1f1dSLionel Sambuc ch = (u_char) pb->data[n];
775*0a6a1f1dSLionel Sambuc if (ch < 32 || ch == 127)
776*0a6a1f1dSLionel Sambuc break;
777*0a6a1f1dSLionel Sambuc }
778*0a6a1f1dSLionel Sambuc inputlen = strlen(data->inputstr);
779*0a6a1f1dSLionel Sambuc
780*0a6a1f1dSLionel Sambuc data->inputstr = xrealloc(data->inputstr, 1, inputlen + n + 1);
781*0a6a1f1dSLionel Sambuc memcpy(data->inputstr + inputlen, pb->data, n);
782*0a6a1f1dSLionel Sambuc data->inputstr[inputlen + n] = '\0';
783*0a6a1f1dSLionel Sambuc break;
784eda6f593SDavid van Moolenbroek case MODEKEYEDIT_ENTER:
785eda6f593SDavid van Moolenbroek np = data->numprefix;
786*0a6a1f1dSLionel Sambuc if (np <= 0)
787eda6f593SDavid van Moolenbroek np = 1;
788eda6f593SDavid van Moolenbroek
789eda6f593SDavid van Moolenbroek switch (data->inputtype) {
790eda6f593SDavid van Moolenbroek case WINDOW_COPY_OFF:
791eda6f593SDavid van Moolenbroek case WINDOW_COPY_JUMPFORWARD:
792eda6f593SDavid van Moolenbroek case WINDOW_COPY_JUMPBACK:
793*0a6a1f1dSLionel Sambuc case WINDOW_COPY_JUMPTOFORWARD:
794*0a6a1f1dSLionel Sambuc case WINDOW_COPY_JUMPTOBACK:
795eda6f593SDavid van Moolenbroek case WINDOW_COPY_NUMERICPREFIX:
796eda6f593SDavid van Moolenbroek break;
797eda6f593SDavid van Moolenbroek case WINDOW_COPY_SEARCHUP:
798eda6f593SDavid van Moolenbroek for (; np != 0; np--)
799eda6f593SDavid van Moolenbroek window_copy_search_up(wp, data->inputstr);
800eda6f593SDavid van Moolenbroek data->searchtype = data->inputtype;
801eda6f593SDavid van Moolenbroek data->searchstr = xstrdup(data->inputstr);
802eda6f593SDavid van Moolenbroek break;
803eda6f593SDavid van Moolenbroek case WINDOW_COPY_SEARCHDOWN:
804eda6f593SDavid van Moolenbroek for (; np != 0; np--)
805eda6f593SDavid van Moolenbroek window_copy_search_down(wp, data->inputstr);
806eda6f593SDavid van Moolenbroek data->searchtype = data->inputtype;
807eda6f593SDavid van Moolenbroek data->searchstr = xstrdup(data->inputstr);
808eda6f593SDavid van Moolenbroek break;
809eda6f593SDavid van Moolenbroek case WINDOW_COPY_GOTOLINE:
810eda6f593SDavid van Moolenbroek window_copy_goto_line(wp, data->inputstr);
811eda6f593SDavid van Moolenbroek *data->inputstr = '\0';
812eda6f593SDavid van Moolenbroek break;
813eda6f593SDavid van Moolenbroek }
814*0a6a1f1dSLionel Sambuc data->numprefix = -1;
815eda6f593SDavid van Moolenbroek return (1);
816eda6f593SDavid van Moolenbroek case MODEKEY_OTHER:
817eda6f593SDavid van Moolenbroek if (key < 32 || key > 126)
818eda6f593SDavid van Moolenbroek break;
819eda6f593SDavid van Moolenbroek inputlen = strlen(data->inputstr) + 2;
820eda6f593SDavid van Moolenbroek
821eda6f593SDavid van Moolenbroek data->inputstr = xrealloc(data->inputstr, 1, inputlen);
822eda6f593SDavid van Moolenbroek data->inputstr[inputlen - 2] = key;
823eda6f593SDavid van Moolenbroek data->inputstr[inputlen - 1] = '\0';
824eda6f593SDavid van Moolenbroek break;
825eda6f593SDavid van Moolenbroek default:
826eda6f593SDavid van Moolenbroek break;
827eda6f593SDavid van Moolenbroek }
828eda6f593SDavid van Moolenbroek
829eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
830eda6f593SDavid van Moolenbroek return (0);
831eda6f593SDavid van Moolenbroek }
832eda6f593SDavid van Moolenbroek
833eda6f593SDavid van Moolenbroek int
window_copy_key_numeric_prefix(struct window_pane * wp,int key)834eda6f593SDavid van Moolenbroek window_copy_key_numeric_prefix(struct window_pane *wp, int key)
835eda6f593SDavid van Moolenbroek {
836eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
837eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
838eda6f593SDavid van Moolenbroek
839eda6f593SDavid van Moolenbroek key &= KEYC_MASK_KEY;
840eda6f593SDavid van Moolenbroek if (key < '0' || key > '9')
841*0a6a1f1dSLionel Sambuc return (1);
842eda6f593SDavid van Moolenbroek
843eda6f593SDavid van Moolenbroek if (data->numprefix >= 100) /* no more than three digits */
844*0a6a1f1dSLionel Sambuc return (0);
845eda6f593SDavid van Moolenbroek data->numprefix = data->numprefix * 10 + key - '0';
846eda6f593SDavid van Moolenbroek
847eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
848*0a6a1f1dSLionel Sambuc return (0);
849eda6f593SDavid van Moolenbroek }
850eda6f593SDavid van Moolenbroek
851eda6f593SDavid van Moolenbroek void
window_copy_mouse(struct window_pane * wp,struct session * sess,struct mouse_event * m)852eda6f593SDavid van Moolenbroek window_copy_mouse(
853eda6f593SDavid van Moolenbroek struct window_pane *wp, struct session *sess, struct mouse_event *m)
854eda6f593SDavid van Moolenbroek {
855eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
856eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
857*0a6a1f1dSLionel Sambuc u_int i;
858eda6f593SDavid van Moolenbroek
859eda6f593SDavid van Moolenbroek if (m->x >= screen_size_x(s))
860eda6f593SDavid van Moolenbroek return;
861eda6f593SDavid van Moolenbroek if (m->y >= screen_size_y(s))
862eda6f593SDavid van Moolenbroek return;
863eda6f593SDavid van Moolenbroek
864eda6f593SDavid van Moolenbroek /* If mouse wheel (buttons 4 and 5), scroll. */
865*0a6a1f1dSLionel Sambuc if (m->event == MOUSE_EVENT_WHEEL) {
866*0a6a1f1dSLionel Sambuc if (m->wheel == MOUSE_WHEEL_UP) {
867eda6f593SDavid van Moolenbroek for (i = 0; i < 5; i++)
868*0a6a1f1dSLionel Sambuc window_copy_cursor_up(wp, 1);
869*0a6a1f1dSLionel Sambuc } else if (m->wheel == MOUSE_WHEEL_DOWN) {
870eda6f593SDavid van Moolenbroek for (i = 0; i < 5; i++)
871*0a6a1f1dSLionel Sambuc window_copy_cursor_down(wp, 1);
872*0a6a1f1dSLionel Sambuc /*
873*0a6a1f1dSLionel Sambuc * We reached the bottom, leave copy mode,
874*0a6a1f1dSLionel Sambuc * but only if no selection is in progress.
875*0a6a1f1dSLionel Sambuc */
876*0a6a1f1dSLionel Sambuc if (data->oy == 0 && !s->sel.flag)
877eda6f593SDavid van Moolenbroek goto reset_mode;
878eda6f593SDavid van Moolenbroek }
879eda6f593SDavid van Moolenbroek return;
880eda6f593SDavid van Moolenbroek }
881eda6f593SDavid van Moolenbroek
882eda6f593SDavid van Moolenbroek /*
883eda6f593SDavid van Moolenbroek * If already reading motion, move the cursor while buttons are still
884eda6f593SDavid van Moolenbroek * pressed, or stop the selection on their release.
885eda6f593SDavid van Moolenbroek */
886eda6f593SDavid van Moolenbroek if (s->mode & MODE_MOUSE_BUTTON) {
887*0a6a1f1dSLionel Sambuc if (~m->event & MOUSE_EVENT_UP) {
888eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, m->x, m->y);
889*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
890eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
891eda6f593SDavid van Moolenbroek return;
892eda6f593SDavid van Moolenbroek }
893eda6f593SDavid van Moolenbroek goto reset_mode;
894eda6f593SDavid van Moolenbroek }
895eda6f593SDavid van Moolenbroek
896eda6f593SDavid van Moolenbroek /* Otherwise if other buttons pressed, start selection and motion. */
897*0a6a1f1dSLionel Sambuc if (~m->event & MOUSE_EVENT_UP) {
898eda6f593SDavid van Moolenbroek s->mode &= ~MODE_MOUSE_STANDARD;
899eda6f593SDavid van Moolenbroek s->mode |= MODE_MOUSE_BUTTON;
900eda6f593SDavid van Moolenbroek
901eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, m->x, m->y);
902eda6f593SDavid van Moolenbroek window_copy_start_selection(wp);
903eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
904eda6f593SDavid van Moolenbroek }
905eda6f593SDavid van Moolenbroek
906eda6f593SDavid van Moolenbroek return;
907eda6f593SDavid van Moolenbroek
908eda6f593SDavid van Moolenbroek reset_mode:
909eda6f593SDavid van Moolenbroek s->mode &= ~MODE_MOUSE_BUTTON;
910eda6f593SDavid van Moolenbroek s->mode |= MODE_MOUSE_STANDARD;
911eda6f593SDavid van Moolenbroek if (sess != NULL) {
912*0a6a1f1dSLionel Sambuc window_copy_copy_selection(wp, -1);
913eda6f593SDavid van Moolenbroek window_pane_reset_mode(wp);
914eda6f593SDavid van Moolenbroek }
915eda6f593SDavid van Moolenbroek }
916eda6f593SDavid van Moolenbroek
917eda6f593SDavid van Moolenbroek void
window_copy_scroll_to(struct window_pane * wp,u_int px,u_int py)918eda6f593SDavid van Moolenbroek window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
919eda6f593SDavid van Moolenbroek {
920eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
921eda6f593SDavid van Moolenbroek struct grid *gd = data->backing->grid;
922eda6f593SDavid van Moolenbroek u_int offset, gap;
923eda6f593SDavid van Moolenbroek
924eda6f593SDavid van Moolenbroek data->cx = px;
925eda6f593SDavid van Moolenbroek
926eda6f593SDavid van Moolenbroek gap = gd->sy / 4;
927eda6f593SDavid van Moolenbroek if (py < gd->sy) {
928eda6f593SDavid van Moolenbroek offset = 0;
929eda6f593SDavid van Moolenbroek data->cy = py;
930eda6f593SDavid van Moolenbroek } else if (py > gd->hsize + gd->sy - gap) {
931eda6f593SDavid van Moolenbroek offset = gd->hsize;
932eda6f593SDavid van Moolenbroek data->cy = py - gd->hsize;
933eda6f593SDavid van Moolenbroek } else {
934eda6f593SDavid van Moolenbroek offset = py + gap - gd->sy;
935eda6f593SDavid van Moolenbroek data->cy = py - offset;
936eda6f593SDavid van Moolenbroek }
937eda6f593SDavid van Moolenbroek data->oy = gd->hsize - offset;
938eda6f593SDavid van Moolenbroek
939*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
940eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
941eda6f593SDavid van Moolenbroek }
942eda6f593SDavid van Moolenbroek
943eda6f593SDavid van Moolenbroek int
window_copy_search_compare(struct grid * gd,u_int px,u_int py,struct grid * sgd,u_int spx,int cis)944eda6f593SDavid van Moolenbroek window_copy_search_compare(
945*0a6a1f1dSLionel Sambuc struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx, int cis)
946eda6f593SDavid van Moolenbroek {
947eda6f593SDavid van Moolenbroek const struct grid_cell *gc, *sgc;
948*0a6a1f1dSLionel Sambuc struct utf8_data ud, sud;
949eda6f593SDavid van Moolenbroek
950eda6f593SDavid van Moolenbroek gc = grid_peek_cell(gd, px, py);
951*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
952eda6f593SDavid van Moolenbroek sgc = grid_peek_cell(sgd, spx, 0);
953*0a6a1f1dSLionel Sambuc grid_cell_get(sgc, &sud);
954eda6f593SDavid van Moolenbroek
955*0a6a1f1dSLionel Sambuc if (ud.size != sud.size || ud.width != sud.width)
956eda6f593SDavid van Moolenbroek return (0);
957eda6f593SDavid van Moolenbroek
958*0a6a1f1dSLionel Sambuc if (cis && ud.size == 1)
959*0a6a1f1dSLionel Sambuc return (tolower(ud.data[0]) == sud.data[0]);
960*0a6a1f1dSLionel Sambuc
961*0a6a1f1dSLionel Sambuc return (memcmp(ud.data, sud.data, ud.size) == 0);
962eda6f593SDavid van Moolenbroek }
963eda6f593SDavid van Moolenbroek
964eda6f593SDavid van Moolenbroek int
window_copy_search_lr(struct grid * gd,struct grid * sgd,u_int * ppx,u_int py,u_int first,u_int last,int cis)965eda6f593SDavid van Moolenbroek window_copy_search_lr(struct grid *gd,
966*0a6a1f1dSLionel Sambuc struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis)
967eda6f593SDavid van Moolenbroek {
968eda6f593SDavid van Moolenbroek u_int ax, bx, px;
969*0a6a1f1dSLionel Sambuc int matched;
970eda6f593SDavid van Moolenbroek
971eda6f593SDavid van Moolenbroek for (ax = first; ax < last; ax++) {
972eda6f593SDavid van Moolenbroek if (ax + sgd->sx >= gd->sx)
973eda6f593SDavid van Moolenbroek break;
974eda6f593SDavid van Moolenbroek for (bx = 0; bx < sgd->sx; bx++) {
975eda6f593SDavid van Moolenbroek px = ax + bx;
976*0a6a1f1dSLionel Sambuc matched = window_copy_search_compare(gd, px, py, sgd,
977*0a6a1f1dSLionel Sambuc bx, cis);
978*0a6a1f1dSLionel Sambuc if (!matched)
979eda6f593SDavid van Moolenbroek break;
980eda6f593SDavid van Moolenbroek }
981eda6f593SDavid van Moolenbroek if (bx == sgd->sx) {
982eda6f593SDavid van Moolenbroek *ppx = ax;
983eda6f593SDavid van Moolenbroek return (1);
984eda6f593SDavid van Moolenbroek }
985eda6f593SDavid van Moolenbroek }
986eda6f593SDavid van Moolenbroek return (0);
987eda6f593SDavid van Moolenbroek }
988eda6f593SDavid van Moolenbroek
989eda6f593SDavid van Moolenbroek int
window_copy_search_rl(struct grid * gd,struct grid * sgd,u_int * ppx,u_int py,u_int first,u_int last,int cis)990eda6f593SDavid van Moolenbroek window_copy_search_rl(struct grid *gd,
991*0a6a1f1dSLionel Sambuc struct grid *sgd, u_int *ppx, u_int py, u_int first, u_int last, int cis)
992eda6f593SDavid van Moolenbroek {
993eda6f593SDavid van Moolenbroek u_int ax, bx, px;
994*0a6a1f1dSLionel Sambuc int matched;
995eda6f593SDavid van Moolenbroek
996eda6f593SDavid van Moolenbroek for (ax = last + 1; ax > first; ax--) {
997eda6f593SDavid van Moolenbroek if (gd->sx - (ax - 1) < sgd->sx)
998eda6f593SDavid van Moolenbroek continue;
999eda6f593SDavid van Moolenbroek for (bx = 0; bx < sgd->sx; bx++) {
1000eda6f593SDavid van Moolenbroek px = ax - 1 + bx;
1001*0a6a1f1dSLionel Sambuc matched = window_copy_search_compare(gd, px, py, sgd,
1002*0a6a1f1dSLionel Sambuc bx, cis);
1003*0a6a1f1dSLionel Sambuc if (!matched)
1004eda6f593SDavid van Moolenbroek break;
1005eda6f593SDavid van Moolenbroek }
1006eda6f593SDavid van Moolenbroek if (bx == sgd->sx) {
1007eda6f593SDavid van Moolenbroek *ppx = ax - 1;
1008eda6f593SDavid van Moolenbroek return (1);
1009eda6f593SDavid van Moolenbroek }
1010eda6f593SDavid van Moolenbroek }
1011eda6f593SDavid van Moolenbroek return (0);
1012eda6f593SDavid van Moolenbroek }
1013eda6f593SDavid van Moolenbroek
1014eda6f593SDavid van Moolenbroek void
window_copy_search_up(struct window_pane * wp,const char * searchstr)1015eda6f593SDavid van Moolenbroek window_copy_search_up(struct window_pane *wp, const char *searchstr)
1016eda6f593SDavid van Moolenbroek {
1017eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1018eda6f593SDavid van Moolenbroek struct screen *s = data->backing, ss;
1019eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
1020eda6f593SDavid van Moolenbroek struct grid *gd = s->grid, *sgd;
1021eda6f593SDavid van Moolenbroek struct grid_cell gc;
1022eda6f593SDavid van Moolenbroek size_t searchlen;
1023eda6f593SDavid van Moolenbroek u_int i, last, fx, fy, px;
1024*0a6a1f1dSLionel Sambuc int utf8flag, n, wrapped, wrapflag, cis;
1025*0a6a1f1dSLionel Sambuc const char *ptr;
1026eda6f593SDavid van Moolenbroek
1027eda6f593SDavid van Moolenbroek if (*searchstr == '\0')
1028eda6f593SDavid van Moolenbroek return;
1029eda6f593SDavid van Moolenbroek utf8flag = options_get_number(&wp->window->options, "utf8");
1030*0a6a1f1dSLionel Sambuc wrapflag = options_get_number(&wp->window->options, "wrap-search");
1031eda6f593SDavid van Moolenbroek searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
1032eda6f593SDavid van Moolenbroek
1033eda6f593SDavid van Moolenbroek screen_init(&ss, searchlen, 1, 0);
1034eda6f593SDavid van Moolenbroek screen_write_start(&ctx, NULL, &ss);
1035eda6f593SDavid van Moolenbroek memcpy(&gc, &grid_default_cell, sizeof gc);
1036eda6f593SDavid van Moolenbroek screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
1037eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
1038eda6f593SDavid van Moolenbroek
1039eda6f593SDavid van Moolenbroek fx = data->cx;
1040eda6f593SDavid van Moolenbroek fy = gd->hsize - data->oy + data->cy;
1041eda6f593SDavid van Moolenbroek
1042eda6f593SDavid van Moolenbroek if (fx == 0) {
1043eda6f593SDavid van Moolenbroek if (fy == 0)
1044eda6f593SDavid van Moolenbroek return;
1045eda6f593SDavid van Moolenbroek fx = gd->sx - 1;
1046eda6f593SDavid van Moolenbroek fy--;
1047eda6f593SDavid van Moolenbroek } else
1048eda6f593SDavid van Moolenbroek fx--;
1049eda6f593SDavid van Moolenbroek n = wrapped = 0;
1050eda6f593SDavid van Moolenbroek
1051*0a6a1f1dSLionel Sambuc cis = 1;
1052*0a6a1f1dSLionel Sambuc for (ptr = searchstr; *ptr != '\0'; ptr++) {
1053*0a6a1f1dSLionel Sambuc if (*ptr != tolower((u_char)*ptr)) {
1054*0a6a1f1dSLionel Sambuc cis = 0;
1055*0a6a1f1dSLionel Sambuc break;
1056*0a6a1f1dSLionel Sambuc }
1057*0a6a1f1dSLionel Sambuc }
1058*0a6a1f1dSLionel Sambuc
1059eda6f593SDavid van Moolenbroek retry:
1060eda6f593SDavid van Moolenbroek sgd = ss.grid;
1061eda6f593SDavid van Moolenbroek for (i = fy + 1; i > 0; i--) {
1062eda6f593SDavid van Moolenbroek last = screen_size_x(s);
1063eda6f593SDavid van Moolenbroek if (i == fy + 1)
1064eda6f593SDavid van Moolenbroek last = fx;
1065*0a6a1f1dSLionel Sambuc n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, last, cis);
1066eda6f593SDavid van Moolenbroek if (n) {
1067eda6f593SDavid van Moolenbroek window_copy_scroll_to(wp, px, i - 1);
1068eda6f593SDavid van Moolenbroek break;
1069eda6f593SDavid van Moolenbroek }
1070eda6f593SDavid van Moolenbroek }
1071*0a6a1f1dSLionel Sambuc if (wrapflag && !n && !wrapped) {
1072eda6f593SDavid van Moolenbroek fx = gd->sx - 1;
1073eda6f593SDavid van Moolenbroek fy = gd->hsize + gd->sy - 1;
1074eda6f593SDavid van Moolenbroek wrapped = 1;
1075eda6f593SDavid van Moolenbroek goto retry;
1076eda6f593SDavid van Moolenbroek }
1077eda6f593SDavid van Moolenbroek
1078eda6f593SDavid van Moolenbroek screen_free(&ss);
1079eda6f593SDavid van Moolenbroek }
1080eda6f593SDavid van Moolenbroek
1081eda6f593SDavid van Moolenbroek void
window_copy_search_down(struct window_pane * wp,const char * searchstr)1082eda6f593SDavid van Moolenbroek window_copy_search_down(struct window_pane *wp, const char *searchstr)
1083eda6f593SDavid van Moolenbroek {
1084eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1085eda6f593SDavid van Moolenbroek struct screen *s = data->backing, ss;
1086eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
1087eda6f593SDavid van Moolenbroek struct grid *gd = s->grid, *sgd;
1088eda6f593SDavid van Moolenbroek struct grid_cell gc;
1089eda6f593SDavid van Moolenbroek size_t searchlen;
1090eda6f593SDavid van Moolenbroek u_int i, first, fx, fy, px;
1091*0a6a1f1dSLionel Sambuc int utf8flag, n, wrapped, wrapflag, cis;
1092*0a6a1f1dSLionel Sambuc const char *ptr;
1093eda6f593SDavid van Moolenbroek
1094eda6f593SDavid van Moolenbroek if (*searchstr == '\0')
1095eda6f593SDavid van Moolenbroek return;
1096eda6f593SDavid van Moolenbroek utf8flag = options_get_number(&wp->window->options, "utf8");
1097*0a6a1f1dSLionel Sambuc wrapflag = options_get_number(&wp->window->options, "wrap-search");
1098eda6f593SDavid van Moolenbroek searchlen = screen_write_strlen(utf8flag, "%s", searchstr);
1099eda6f593SDavid van Moolenbroek
1100eda6f593SDavid van Moolenbroek screen_init(&ss, searchlen, 1, 0);
1101eda6f593SDavid van Moolenbroek screen_write_start(&ctx, NULL, &ss);
1102eda6f593SDavid van Moolenbroek memcpy(&gc, &grid_default_cell, sizeof gc);
1103eda6f593SDavid van Moolenbroek screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr);
1104eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
1105eda6f593SDavid van Moolenbroek
1106eda6f593SDavid van Moolenbroek fx = data->cx;
1107eda6f593SDavid van Moolenbroek fy = gd->hsize - data->oy + data->cy;
1108eda6f593SDavid van Moolenbroek
1109eda6f593SDavid van Moolenbroek if (fx == gd->sx - 1) {
1110eda6f593SDavid van Moolenbroek if (fy == gd->hsize + gd->sy)
1111eda6f593SDavid van Moolenbroek return;
1112eda6f593SDavid van Moolenbroek fx = 0;
1113eda6f593SDavid van Moolenbroek fy++;
1114eda6f593SDavid van Moolenbroek } else
1115eda6f593SDavid van Moolenbroek fx++;
1116eda6f593SDavid van Moolenbroek n = wrapped = 0;
1117eda6f593SDavid van Moolenbroek
1118*0a6a1f1dSLionel Sambuc cis = 1;
1119*0a6a1f1dSLionel Sambuc for (ptr = searchstr; *ptr != '\0'; ptr++) {
1120*0a6a1f1dSLionel Sambuc if (*ptr != tolower((u_char)*ptr)) {
1121*0a6a1f1dSLionel Sambuc cis = 0;
1122*0a6a1f1dSLionel Sambuc break;
1123*0a6a1f1dSLionel Sambuc }
1124*0a6a1f1dSLionel Sambuc }
1125*0a6a1f1dSLionel Sambuc
1126eda6f593SDavid van Moolenbroek retry:
1127eda6f593SDavid van Moolenbroek sgd = ss.grid;
1128*0a6a1f1dSLionel Sambuc for (i = fy + 1; i < gd->hsize + gd->sy + 1; i++) {
1129eda6f593SDavid van Moolenbroek first = 0;
1130eda6f593SDavid van Moolenbroek if (i == fy + 1)
1131eda6f593SDavid van Moolenbroek first = fx;
1132*0a6a1f1dSLionel Sambuc n = window_copy_search_lr(gd, sgd, &px, i - 1, first, gd->sx,
1133*0a6a1f1dSLionel Sambuc cis);
1134eda6f593SDavid van Moolenbroek if (n) {
1135eda6f593SDavid van Moolenbroek window_copy_scroll_to(wp, px, i - 1);
1136eda6f593SDavid van Moolenbroek break;
1137eda6f593SDavid van Moolenbroek }
1138eda6f593SDavid van Moolenbroek }
1139*0a6a1f1dSLionel Sambuc if (wrapflag && !n && !wrapped) {
1140eda6f593SDavid van Moolenbroek fx = 0;
1141eda6f593SDavid van Moolenbroek fy = 0;
1142eda6f593SDavid van Moolenbroek wrapped = 1;
1143eda6f593SDavid van Moolenbroek goto retry;
1144eda6f593SDavid van Moolenbroek }
1145eda6f593SDavid van Moolenbroek
1146eda6f593SDavid van Moolenbroek screen_free(&ss);
1147eda6f593SDavid van Moolenbroek }
1148eda6f593SDavid van Moolenbroek
1149eda6f593SDavid van Moolenbroek void
window_copy_goto_line(struct window_pane * wp,const char * linestr)1150eda6f593SDavid van Moolenbroek window_copy_goto_line(struct window_pane *wp, const char *linestr)
1151eda6f593SDavid van Moolenbroek {
1152eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1153eda6f593SDavid van Moolenbroek const char *errstr;
1154eda6f593SDavid van Moolenbroek u_int lineno;
1155eda6f593SDavid van Moolenbroek
1156eda6f593SDavid van Moolenbroek lineno = strtonum(linestr, 0, screen_hsize(data->backing), &errstr);
1157eda6f593SDavid van Moolenbroek if (errstr != NULL)
1158eda6f593SDavid van Moolenbroek return;
1159eda6f593SDavid van Moolenbroek
1160eda6f593SDavid van Moolenbroek data->oy = lineno;
1161*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
1162eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
1163eda6f593SDavid van Moolenbroek }
1164eda6f593SDavid van Moolenbroek
1165eda6f593SDavid van Moolenbroek void
window_copy_write_line(struct window_pane * wp,struct screen_write_ctx * ctx,u_int py)1166eda6f593SDavid van Moolenbroek window_copy_write_line(
1167eda6f593SDavid van Moolenbroek struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
1168eda6f593SDavid van Moolenbroek {
1169eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1170eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1171eda6f593SDavid van Moolenbroek struct options *oo = &wp->window->options;
1172eda6f593SDavid van Moolenbroek struct grid_cell gc;
1173*0a6a1f1dSLionel Sambuc char hdr[512];
1174*0a6a1f1dSLionel Sambuc size_t last, xoff = 0, size = 0, limit;
1175eda6f593SDavid van Moolenbroek
1176*0a6a1f1dSLionel Sambuc style_apply(&gc, oo, "mode-style");
1177eda6f593SDavid van Moolenbroek
1178eda6f593SDavid van Moolenbroek last = screen_size_y(s) - 1;
1179eda6f593SDavid van Moolenbroek if (py == 0) {
1180eda6f593SDavid van Moolenbroek size = xsnprintf(hdr, sizeof hdr,
1181eda6f593SDavid van Moolenbroek "[%u/%u]", data->oy, screen_hsize(data->backing));
1182eda6f593SDavid van Moolenbroek if (size > screen_size_x(s))
1183eda6f593SDavid van Moolenbroek size = screen_size_x(s);
1184eda6f593SDavid van Moolenbroek screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
1185eda6f593SDavid van Moolenbroek screen_write_puts(ctx, &gc, "%s", hdr);
1186eda6f593SDavid van Moolenbroek } else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
1187*0a6a1f1dSLionel Sambuc limit = sizeof hdr;
1188*0a6a1f1dSLionel Sambuc if (limit > screen_size_x(s))
1189*0a6a1f1dSLionel Sambuc limit = screen_size_x(s);
1190eda6f593SDavid van Moolenbroek if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
1191*0a6a1f1dSLionel Sambuc xoff = size = xsnprintf(hdr, limit,
1192eda6f593SDavid van Moolenbroek "Repeat: %u", data->numprefix);
1193eda6f593SDavid van Moolenbroek } else {
1194*0a6a1f1dSLionel Sambuc xoff = size = xsnprintf(hdr, limit,
1195eda6f593SDavid van Moolenbroek "%s: %s", data->inputprompt, data->inputstr);
1196eda6f593SDavid van Moolenbroek }
1197eda6f593SDavid van Moolenbroek screen_write_cursormove(ctx, 0, last);
1198eda6f593SDavid van Moolenbroek screen_write_puts(ctx, &gc, "%s", hdr);
1199eda6f593SDavid van Moolenbroek } else
1200eda6f593SDavid van Moolenbroek size = 0;
1201eda6f593SDavid van Moolenbroek
1202eda6f593SDavid van Moolenbroek screen_write_cursormove(ctx, xoff, py);
1203eda6f593SDavid van Moolenbroek screen_write_copy(ctx, data->backing, xoff,
1204eda6f593SDavid van Moolenbroek (screen_hsize(data->backing) - data->oy) + py,
1205eda6f593SDavid van Moolenbroek screen_size_x(s) - size, 1);
1206eda6f593SDavid van Moolenbroek
1207eda6f593SDavid van Moolenbroek if (py == data->cy && data->cx == screen_size_x(s)) {
1208eda6f593SDavid van Moolenbroek memcpy(&gc, &grid_default_cell, sizeof gc);
1209eda6f593SDavid van Moolenbroek screen_write_cursormove(ctx, screen_size_x(s) - 1, py);
1210eda6f593SDavid van Moolenbroek screen_write_putc(ctx, &gc, '$');
1211eda6f593SDavid van Moolenbroek }
1212eda6f593SDavid van Moolenbroek }
1213eda6f593SDavid van Moolenbroek
1214eda6f593SDavid van Moolenbroek void
window_copy_write_lines(struct window_pane * wp,struct screen_write_ctx * ctx,u_int py,u_int ny)1215eda6f593SDavid van Moolenbroek window_copy_write_lines(
1216eda6f593SDavid van Moolenbroek struct window_pane *wp, struct screen_write_ctx *ctx, u_int py, u_int ny)
1217eda6f593SDavid van Moolenbroek {
1218eda6f593SDavid van Moolenbroek u_int yy;
1219eda6f593SDavid van Moolenbroek
1220eda6f593SDavid van Moolenbroek for (yy = py; yy < py + ny; yy++)
1221eda6f593SDavid van Moolenbroek window_copy_write_line(wp, ctx, py);
1222eda6f593SDavid van Moolenbroek }
1223eda6f593SDavid van Moolenbroek
1224eda6f593SDavid van Moolenbroek void
window_copy_redraw_lines(struct window_pane * wp,u_int py,u_int ny)1225eda6f593SDavid van Moolenbroek window_copy_redraw_lines(struct window_pane *wp, u_int py, u_int ny)
1226eda6f593SDavid van Moolenbroek {
1227eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1228eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
1229eda6f593SDavid van Moolenbroek u_int i;
1230eda6f593SDavid van Moolenbroek
1231eda6f593SDavid van Moolenbroek screen_write_start(&ctx, wp, NULL);
1232eda6f593SDavid van Moolenbroek for (i = py; i < py + ny; i++)
1233eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, i);
1234eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, data->cx, data->cy);
1235eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
1236eda6f593SDavid van Moolenbroek }
1237eda6f593SDavid van Moolenbroek
1238eda6f593SDavid van Moolenbroek void
window_copy_redraw_screen(struct window_pane * wp)1239eda6f593SDavid van Moolenbroek window_copy_redraw_screen(struct window_pane *wp)
1240eda6f593SDavid van Moolenbroek {
1241eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1242eda6f593SDavid van Moolenbroek
1243eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, 0, screen_size_y(&data->screen));
1244eda6f593SDavid van Moolenbroek }
1245eda6f593SDavid van Moolenbroek
1246eda6f593SDavid van Moolenbroek void
window_copy_update_cursor(struct window_pane * wp,u_int cx,u_int cy)1247eda6f593SDavid van Moolenbroek window_copy_update_cursor(struct window_pane *wp, u_int cx, u_int cy)
1248eda6f593SDavid van Moolenbroek {
1249eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1250eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1251eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
1252eda6f593SDavid van Moolenbroek u_int old_cx, old_cy;
1253eda6f593SDavid van Moolenbroek
1254eda6f593SDavid van Moolenbroek old_cx = data->cx; old_cy = data->cy;
1255eda6f593SDavid van Moolenbroek data->cx = cx; data->cy = cy;
1256eda6f593SDavid van Moolenbroek if (old_cx == screen_size_x(s))
1257eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, old_cy, 1);
1258eda6f593SDavid van Moolenbroek if (data->cx == screen_size_x(s))
1259eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1260eda6f593SDavid van Moolenbroek else {
1261eda6f593SDavid van Moolenbroek screen_write_start(&ctx, wp, NULL);
1262eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, data->cx, data->cy);
1263eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
1264eda6f593SDavid van Moolenbroek }
1265eda6f593SDavid van Moolenbroek }
1266eda6f593SDavid van Moolenbroek
1267eda6f593SDavid van Moolenbroek void
window_copy_start_selection(struct window_pane * wp)1268eda6f593SDavid van Moolenbroek window_copy_start_selection(struct window_pane *wp)
1269eda6f593SDavid van Moolenbroek {
1270eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1271eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1272eda6f593SDavid van Moolenbroek
1273eda6f593SDavid van Moolenbroek data->selx = data->cx;
1274eda6f593SDavid van Moolenbroek data->sely = screen_hsize(data->backing) + data->cy - data->oy;
1275eda6f593SDavid van Moolenbroek
1276eda6f593SDavid van Moolenbroek s->sel.flag = 1;
1277*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
1278eda6f593SDavid van Moolenbroek }
1279eda6f593SDavid van Moolenbroek
1280eda6f593SDavid van Moolenbroek int
window_copy_update_selection(struct window_pane * wp,int may_redraw)1281*0a6a1f1dSLionel Sambuc window_copy_update_selection(struct window_pane *wp, int may_redraw)
1282eda6f593SDavid van Moolenbroek {
1283eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1284eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1285eda6f593SDavid van Moolenbroek struct options *oo = &wp->window->options;
1286eda6f593SDavid van Moolenbroek struct grid_cell gc;
1287eda6f593SDavid van Moolenbroek u_int sx, sy, ty, cy;
1288eda6f593SDavid van Moolenbroek
1289eda6f593SDavid van Moolenbroek if (!s->sel.flag)
1290eda6f593SDavid van Moolenbroek return (0);
1291eda6f593SDavid van Moolenbroek
1292eda6f593SDavid van Moolenbroek /* Set colours. */
1293*0a6a1f1dSLionel Sambuc style_apply(&gc, oo, "mode-style");
1294eda6f593SDavid van Moolenbroek
1295eda6f593SDavid van Moolenbroek /* Find top of screen. */
1296eda6f593SDavid van Moolenbroek ty = screen_hsize(data->backing) - data->oy;
1297eda6f593SDavid van Moolenbroek
1298eda6f593SDavid van Moolenbroek /* Adjust the selection. */
1299eda6f593SDavid van Moolenbroek sx = data->selx;
1300eda6f593SDavid van Moolenbroek sy = data->sely;
1301eda6f593SDavid van Moolenbroek if (sy < ty) { /* above screen */
1302eda6f593SDavid van Moolenbroek if (!data->rectflag)
1303eda6f593SDavid van Moolenbroek sx = 0;
1304eda6f593SDavid van Moolenbroek sy = 0;
1305eda6f593SDavid van Moolenbroek } else if (sy > ty + screen_size_y(s) - 1) { /* below screen */
1306eda6f593SDavid van Moolenbroek if (!data->rectflag)
1307eda6f593SDavid van Moolenbroek sx = screen_size_x(s) - 1;
1308eda6f593SDavid van Moolenbroek sy = screen_size_y(s) - 1;
1309eda6f593SDavid van Moolenbroek } else
1310eda6f593SDavid van Moolenbroek sy -= ty;
1311eda6f593SDavid van Moolenbroek sy = screen_hsize(s) + sy;
1312eda6f593SDavid van Moolenbroek
1313eda6f593SDavid van Moolenbroek screen_set_selection(s,
1314eda6f593SDavid van Moolenbroek sx, sy, data->cx, screen_hsize(s) + data->cy, data->rectflag, &gc);
1315eda6f593SDavid van Moolenbroek
1316*0a6a1f1dSLionel Sambuc if (data->rectflag && may_redraw) {
1317eda6f593SDavid van Moolenbroek /*
1318eda6f593SDavid van Moolenbroek * Can't rely on the caller to redraw the right lines for
1319eda6f593SDavid van Moolenbroek * rectangle selection - find the highest line and the number
1320eda6f593SDavid van Moolenbroek * of lines, and redraw just past that in both directions
1321eda6f593SDavid van Moolenbroek */
1322eda6f593SDavid van Moolenbroek cy = data->cy;
1323eda6f593SDavid van Moolenbroek if (sy < cy)
1324eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, sy, cy - sy + 1);
1325eda6f593SDavid van Moolenbroek else
1326eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, cy, sy - cy + 1);
1327eda6f593SDavid van Moolenbroek }
1328eda6f593SDavid van Moolenbroek
1329eda6f593SDavid van Moolenbroek return (1);
1330eda6f593SDavid van Moolenbroek }
1331eda6f593SDavid van Moolenbroek
1332*0a6a1f1dSLionel Sambuc void *
window_copy_get_selection(struct window_pane * wp,size_t * len)1333*0a6a1f1dSLionel Sambuc window_copy_get_selection(struct window_pane *wp, size_t *len)
1334eda6f593SDavid van Moolenbroek {
1335eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1336eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1337eda6f593SDavid van Moolenbroek char *buf;
1338eda6f593SDavid van Moolenbroek size_t off;
1339*0a6a1f1dSLionel Sambuc u_int i, xx, yy, sx, sy, ex, ey;
1340eda6f593SDavid van Moolenbroek u_int firstsx, lastex, restex, restsx;
1341eda6f593SDavid van Moolenbroek int keys;
1342eda6f593SDavid van Moolenbroek
1343eda6f593SDavid van Moolenbroek if (!s->sel.flag)
1344*0a6a1f1dSLionel Sambuc return (NULL);
1345eda6f593SDavid van Moolenbroek
1346eda6f593SDavid van Moolenbroek buf = xmalloc(1);
1347eda6f593SDavid van Moolenbroek off = 0;
1348eda6f593SDavid van Moolenbroek
1349eda6f593SDavid van Moolenbroek *buf = '\0';
1350eda6f593SDavid van Moolenbroek
1351eda6f593SDavid van Moolenbroek /*
1352eda6f593SDavid van Moolenbroek * The selection extends from selx,sely to (adjusted) cx,cy on
1353eda6f593SDavid van Moolenbroek * the base screen.
1354eda6f593SDavid van Moolenbroek */
1355eda6f593SDavid van Moolenbroek
1356eda6f593SDavid van Moolenbroek /* Find start and end. */
1357eda6f593SDavid van Moolenbroek xx = data->cx;
1358eda6f593SDavid van Moolenbroek yy = screen_hsize(data->backing) + data->cy - data->oy;
1359eda6f593SDavid van Moolenbroek if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
1360eda6f593SDavid van Moolenbroek sx = xx; sy = yy;
1361eda6f593SDavid van Moolenbroek ex = data->selx; ey = data->sely;
1362eda6f593SDavid van Moolenbroek } else {
1363eda6f593SDavid van Moolenbroek sx = data->selx; sy = data->sely;
1364eda6f593SDavid van Moolenbroek ex = xx; ey = yy;
1365eda6f593SDavid van Moolenbroek }
1366eda6f593SDavid van Moolenbroek
1367eda6f593SDavid van Moolenbroek /* Trim ex to end of line. */
1368eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, ey);
1369eda6f593SDavid van Moolenbroek if (ex > xx)
1370eda6f593SDavid van Moolenbroek ex = xx;
1371eda6f593SDavid van Moolenbroek
1372eda6f593SDavid van Moolenbroek /*
1373eda6f593SDavid van Moolenbroek * Deal with rectangle-copy if necessary; four situations: start of
1374eda6f593SDavid van Moolenbroek * first line (firstsx), end of last line (lastex), start (restsx) and
1375eda6f593SDavid van Moolenbroek * end (restex) of all other lines.
1376eda6f593SDavid van Moolenbroek */
1377eda6f593SDavid van Moolenbroek xx = screen_size_x(s);
1378eda6f593SDavid van Moolenbroek
1379eda6f593SDavid van Moolenbroek /*
1380eda6f593SDavid van Moolenbroek * Behave according to mode-keys. If it is emacs, copy like emacs,
1381eda6f593SDavid van Moolenbroek * keeping the top-left-most character, and dropping the
1382eda6f593SDavid van Moolenbroek * bottom-right-most, regardless of copy direction. If it is vi, also
1383eda6f593SDavid van Moolenbroek * keep bottom-right-most character.
1384eda6f593SDavid van Moolenbroek */
1385eda6f593SDavid van Moolenbroek keys = options_get_number(&wp->window->options, "mode-keys");
1386eda6f593SDavid van Moolenbroek if (data->rectflag) {
1387eda6f593SDavid van Moolenbroek /*
1388eda6f593SDavid van Moolenbroek * Need to ignore the column with the cursor in it, which for
1389eda6f593SDavid van Moolenbroek * rectangular copy means knowing which side the cursor is on.
1390eda6f593SDavid van Moolenbroek */
1391eda6f593SDavid van Moolenbroek if (data->selx < data->cx) {
1392eda6f593SDavid van Moolenbroek /* Selection start is on the left. */
1393eda6f593SDavid van Moolenbroek if (keys == MODEKEY_EMACS) {
1394eda6f593SDavid van Moolenbroek lastex = data->cx;
1395eda6f593SDavid van Moolenbroek restex = data->cx;
1396eda6f593SDavid van Moolenbroek }
1397eda6f593SDavid van Moolenbroek else {
1398eda6f593SDavid van Moolenbroek lastex = data->cx + 1;
1399eda6f593SDavid van Moolenbroek restex = data->cx + 1;
1400eda6f593SDavid van Moolenbroek }
1401eda6f593SDavid van Moolenbroek firstsx = data->selx;
1402eda6f593SDavid van Moolenbroek restsx = data->selx;
1403eda6f593SDavid van Moolenbroek } else {
1404eda6f593SDavid van Moolenbroek /* Cursor is on the left. */
1405eda6f593SDavid van Moolenbroek lastex = data->selx + 1;
1406eda6f593SDavid van Moolenbroek restex = data->selx + 1;
1407eda6f593SDavid van Moolenbroek firstsx = data->cx;
1408eda6f593SDavid van Moolenbroek restsx = data->cx;
1409eda6f593SDavid van Moolenbroek }
1410eda6f593SDavid van Moolenbroek } else {
1411eda6f593SDavid van Moolenbroek if (keys == MODEKEY_EMACS)
1412eda6f593SDavid van Moolenbroek lastex = ex;
1413eda6f593SDavid van Moolenbroek else
1414eda6f593SDavid van Moolenbroek lastex = ex + 1;
1415eda6f593SDavid van Moolenbroek restex = xx;
1416eda6f593SDavid van Moolenbroek firstsx = sx;
1417eda6f593SDavid van Moolenbroek restsx = 0;
1418eda6f593SDavid van Moolenbroek }
1419eda6f593SDavid van Moolenbroek
1420eda6f593SDavid van Moolenbroek /* Copy the lines. */
1421eda6f593SDavid van Moolenbroek if (sy == ey)
1422eda6f593SDavid van Moolenbroek window_copy_copy_line(wp, &buf, &off, sy, firstsx, lastex);
1423eda6f593SDavid van Moolenbroek else {
1424eda6f593SDavid van Moolenbroek window_copy_copy_line(wp, &buf, &off, sy, firstsx, restex);
1425eda6f593SDavid van Moolenbroek if (ey - sy > 1) {
1426eda6f593SDavid van Moolenbroek for (i = sy + 1; i < ey; i++) {
1427eda6f593SDavid van Moolenbroek window_copy_copy_line(
1428eda6f593SDavid van Moolenbroek wp, &buf, &off, i, restsx, restex);
1429eda6f593SDavid van Moolenbroek }
1430eda6f593SDavid van Moolenbroek }
1431eda6f593SDavid van Moolenbroek window_copy_copy_line(wp, &buf, &off, ey, restsx, lastex);
1432eda6f593SDavid van Moolenbroek }
1433eda6f593SDavid van Moolenbroek
1434eda6f593SDavid van Moolenbroek /* Don't bother if no data. */
1435eda6f593SDavid van Moolenbroek if (off == 0) {
1436*0a6a1f1dSLionel Sambuc free(buf);
1437*0a6a1f1dSLionel Sambuc return (NULL);
1438eda6f593SDavid van Moolenbroek }
1439*0a6a1f1dSLionel Sambuc *len = off - 1; /* remove final \n */
1440*0a6a1f1dSLionel Sambuc return (buf);
1441*0a6a1f1dSLionel Sambuc }
1442eda6f593SDavid van Moolenbroek
1443*0a6a1f1dSLionel Sambuc void
window_copy_copy_buffer(struct window_pane * wp,int idx,void * buf,size_t len)1444*0a6a1f1dSLionel Sambuc window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
1445*0a6a1f1dSLionel Sambuc {
1446*0a6a1f1dSLionel Sambuc u_int limit;
1447*0a6a1f1dSLionel Sambuc struct screen_write_ctx ctx;
1448eda6f593SDavid van Moolenbroek
1449*0a6a1f1dSLionel Sambuc if (options_get_number(&global_options, "set-clipboard")) {
1450*0a6a1f1dSLionel Sambuc screen_write_start(&ctx, wp, NULL);
1451*0a6a1f1dSLionel Sambuc screen_write_setselection(&ctx, buf, len);
1452*0a6a1f1dSLionel Sambuc screen_write_stop(&ctx);
1453*0a6a1f1dSLionel Sambuc }
1454*0a6a1f1dSLionel Sambuc
1455*0a6a1f1dSLionel Sambuc if (idx == -1) {
1456eda6f593SDavid van Moolenbroek limit = options_get_number(&global_options, "buffer-limit");
1457*0a6a1f1dSLionel Sambuc paste_add(&global_buffers, buf, len, limit);
1458*0a6a1f1dSLionel Sambuc } else if (paste_replace(&global_buffers, idx, buf, len) != 0)
1459*0a6a1f1dSLionel Sambuc free(buf);
1460*0a6a1f1dSLionel Sambuc }
1461*0a6a1f1dSLionel Sambuc
1462*0a6a1f1dSLionel Sambuc void
window_copy_copy_pipe(struct window_pane * wp,struct session * sess,int idx,const char * arg)1463*0a6a1f1dSLionel Sambuc window_copy_copy_pipe(
1464*0a6a1f1dSLionel Sambuc struct window_pane *wp, struct session *sess, int idx, const char *arg)
1465*0a6a1f1dSLionel Sambuc {
1466*0a6a1f1dSLionel Sambuc void *buf;
1467*0a6a1f1dSLionel Sambuc size_t len;
1468*0a6a1f1dSLionel Sambuc struct job *job;
1469*0a6a1f1dSLionel Sambuc
1470*0a6a1f1dSLionel Sambuc
1471*0a6a1f1dSLionel Sambuc buf = window_copy_get_selection(wp, &len);
1472*0a6a1f1dSLionel Sambuc if (buf == NULL)
1473*0a6a1f1dSLionel Sambuc return;
1474*0a6a1f1dSLionel Sambuc
1475*0a6a1f1dSLionel Sambuc job = job_run(arg, sess, NULL, NULL, NULL);
1476*0a6a1f1dSLionel Sambuc bufferevent_write(job->event, buf, len);
1477*0a6a1f1dSLionel Sambuc
1478*0a6a1f1dSLionel Sambuc window_copy_copy_buffer(wp, idx, buf, len);
1479*0a6a1f1dSLionel Sambuc }
1480*0a6a1f1dSLionel Sambuc
1481*0a6a1f1dSLionel Sambuc void
window_copy_copy_selection(struct window_pane * wp,int idx)1482*0a6a1f1dSLionel Sambuc window_copy_copy_selection(struct window_pane *wp, int idx)
1483*0a6a1f1dSLionel Sambuc {
1484*0a6a1f1dSLionel Sambuc void* buf;
1485*0a6a1f1dSLionel Sambuc size_t len;
1486*0a6a1f1dSLionel Sambuc
1487*0a6a1f1dSLionel Sambuc buf = window_copy_get_selection(wp, &len);
1488*0a6a1f1dSLionel Sambuc if (buf == NULL)
1489*0a6a1f1dSLionel Sambuc return;
1490*0a6a1f1dSLionel Sambuc
1491*0a6a1f1dSLionel Sambuc window_copy_copy_buffer(wp, idx, buf, len);
1492eda6f593SDavid van Moolenbroek }
1493eda6f593SDavid van Moolenbroek
1494eda6f593SDavid van Moolenbroek void
window_copy_copy_line(struct window_pane * wp,char ** buf,size_t * off,u_int sy,u_int sx,u_int ex)1495eda6f593SDavid van Moolenbroek window_copy_copy_line(struct window_pane *wp,
1496eda6f593SDavid van Moolenbroek char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
1497eda6f593SDavid van Moolenbroek {
1498eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1499eda6f593SDavid van Moolenbroek struct grid *gd = data->backing->grid;
1500eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1501eda6f593SDavid van Moolenbroek struct grid_line *gl;
1502*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1503eda6f593SDavid van Moolenbroek u_int i, xx, wrapped = 0;
1504eda6f593SDavid van Moolenbroek
1505eda6f593SDavid van Moolenbroek if (sx > ex)
1506eda6f593SDavid van Moolenbroek return;
1507eda6f593SDavid van Moolenbroek
1508eda6f593SDavid van Moolenbroek /*
1509eda6f593SDavid van Moolenbroek * Work out if the line was wrapped at the screen edge and all of it is
1510eda6f593SDavid van Moolenbroek * on screen.
1511eda6f593SDavid van Moolenbroek */
1512eda6f593SDavid van Moolenbroek gl = &gd->linedata[sy];
1513eda6f593SDavid van Moolenbroek if (gl->flags & GRID_LINE_WRAPPED && gl->cellsize <= gd->sx)
1514eda6f593SDavid van Moolenbroek wrapped = 1;
1515eda6f593SDavid van Moolenbroek
1516eda6f593SDavid van Moolenbroek /* If the line was wrapped, don't strip spaces (use the full length). */
1517eda6f593SDavid van Moolenbroek if (wrapped)
1518eda6f593SDavid van Moolenbroek xx = gl->cellsize;
1519eda6f593SDavid van Moolenbroek else
1520eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, sy);
1521eda6f593SDavid van Moolenbroek if (ex > xx)
1522eda6f593SDavid van Moolenbroek ex = xx;
1523eda6f593SDavid van Moolenbroek if (sx > xx)
1524eda6f593SDavid van Moolenbroek sx = xx;
1525eda6f593SDavid van Moolenbroek
1526eda6f593SDavid van Moolenbroek if (sx < ex) {
1527eda6f593SDavid van Moolenbroek for (i = sx; i < ex; i++) {
1528eda6f593SDavid van Moolenbroek gc = grid_peek_cell(gd, i, sy);
1529eda6f593SDavid van Moolenbroek if (gc->flags & GRID_FLAG_PADDING)
1530eda6f593SDavid van Moolenbroek continue;
1531*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1532*0a6a1f1dSLionel Sambuc
1533*0a6a1f1dSLionel Sambuc *buf = xrealloc(*buf, 1, (*off) + ud.size);
1534*0a6a1f1dSLionel Sambuc memcpy(*buf + *off, ud.data, ud.size);
1535*0a6a1f1dSLionel Sambuc *off += ud.size;
1536eda6f593SDavid van Moolenbroek }
1537eda6f593SDavid van Moolenbroek }
1538eda6f593SDavid van Moolenbroek
1539eda6f593SDavid van Moolenbroek /* Only add a newline if the line wasn't wrapped. */
1540eda6f593SDavid van Moolenbroek if (!wrapped || ex != xx) {
1541eda6f593SDavid van Moolenbroek *buf = xrealloc(*buf, 1, (*off) + 1);
1542eda6f593SDavid van Moolenbroek (*buf)[(*off)++] = '\n';
1543eda6f593SDavid van Moolenbroek }
1544eda6f593SDavid van Moolenbroek }
1545eda6f593SDavid van Moolenbroek
1546eda6f593SDavid van Moolenbroek void
window_copy_clear_selection(struct window_pane * wp)1547eda6f593SDavid van Moolenbroek window_copy_clear_selection(struct window_pane *wp)
1548eda6f593SDavid van Moolenbroek {
1549eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1550eda6f593SDavid van Moolenbroek u_int px, py;
1551eda6f593SDavid van Moolenbroek
1552eda6f593SDavid van Moolenbroek screen_clear_selection(&data->screen);
1553eda6f593SDavid van Moolenbroek
1554eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
1555eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1556eda6f593SDavid van Moolenbroek if (data->cx > px)
1557eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1558eda6f593SDavid van Moolenbroek }
1559eda6f593SDavid van Moolenbroek
1560eda6f593SDavid van Moolenbroek int
window_copy_in_set(struct window_pane * wp,u_int px,u_int py,const char * set)1561eda6f593SDavid van Moolenbroek window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
1562eda6f593SDavid van Moolenbroek {
1563eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1564eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1565*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1566eda6f593SDavid van Moolenbroek
1567eda6f593SDavid van Moolenbroek gc = grid_peek_cell(data->backing->grid, px, py);
1568*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1569*0a6a1f1dSLionel Sambuc if (ud.size != 1 || gc->flags & GRID_FLAG_PADDING)
1570eda6f593SDavid van Moolenbroek return (0);
1571*0a6a1f1dSLionel Sambuc if (*ud.data == 0x00 || *ud.data == 0x7f)
1572eda6f593SDavid van Moolenbroek return (0);
1573*0a6a1f1dSLionel Sambuc return (strchr(set, *ud.data) != NULL);
1574eda6f593SDavid van Moolenbroek }
1575eda6f593SDavid van Moolenbroek
1576eda6f593SDavid van Moolenbroek u_int
window_copy_find_length(struct window_pane * wp,u_int py)1577eda6f593SDavid van Moolenbroek window_copy_find_length(struct window_pane *wp, u_int py)
1578eda6f593SDavid van Moolenbroek {
1579eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1580eda6f593SDavid van Moolenbroek struct screen *s = data->backing;
1581eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1582*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1583eda6f593SDavid van Moolenbroek u_int px;
1584eda6f593SDavid van Moolenbroek
1585eda6f593SDavid van Moolenbroek /*
1586eda6f593SDavid van Moolenbroek * If the pane has been resized, its grid can contain old overlong
1587eda6f593SDavid van Moolenbroek * lines. grid_peek_cell does not allow accessing cells beyond the
1588eda6f593SDavid van Moolenbroek * width of the grid, and screen_write_copy treats them as spaces, so
1589eda6f593SDavid van Moolenbroek * ignore them here too.
1590eda6f593SDavid van Moolenbroek */
1591eda6f593SDavid van Moolenbroek px = s->grid->linedata[py].cellsize;
1592eda6f593SDavid van Moolenbroek if (px > screen_size_x(s))
1593eda6f593SDavid van Moolenbroek px = screen_size_x(s);
1594eda6f593SDavid van Moolenbroek while (px > 0) {
1595eda6f593SDavid van Moolenbroek gc = grid_peek_cell(s->grid, px - 1, py);
1596*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1597*0a6a1f1dSLionel Sambuc if (ud.size != 1 || *ud.data != ' ')
1598eda6f593SDavid van Moolenbroek break;
1599eda6f593SDavid van Moolenbroek px--;
1600eda6f593SDavid van Moolenbroek }
1601eda6f593SDavid van Moolenbroek return (px);
1602eda6f593SDavid van Moolenbroek }
1603eda6f593SDavid van Moolenbroek
1604eda6f593SDavid van Moolenbroek void
window_copy_cursor_start_of_line(struct window_pane * wp)1605eda6f593SDavid van Moolenbroek window_copy_cursor_start_of_line(struct window_pane *wp)
1606eda6f593SDavid van Moolenbroek {
1607eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1608eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1609eda6f593SDavid van Moolenbroek struct grid *gd = back_s->grid;
1610eda6f593SDavid van Moolenbroek u_int py;
1611eda6f593SDavid van Moolenbroek
1612eda6f593SDavid van Moolenbroek if (data->cx == 0) {
1613eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1614eda6f593SDavid van Moolenbroek while (py > 0 && gd->linedata[py-1].flags & GRID_LINE_WRAPPED) {
1615eda6f593SDavid van Moolenbroek window_copy_cursor_up(wp, 0);
1616eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1617eda6f593SDavid van Moolenbroek }
1618eda6f593SDavid van Moolenbroek }
1619eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, 0, data->cy);
1620*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1621eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1622eda6f593SDavid van Moolenbroek }
1623eda6f593SDavid van Moolenbroek
1624eda6f593SDavid van Moolenbroek void
window_copy_cursor_back_to_indentation(struct window_pane * wp)1625eda6f593SDavid van Moolenbroek window_copy_cursor_back_to_indentation(struct window_pane *wp)
1626eda6f593SDavid van Moolenbroek {
1627eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1628eda6f593SDavid van Moolenbroek u_int px, py, xx;
1629eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1630*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1631eda6f593SDavid van Moolenbroek
1632eda6f593SDavid van Moolenbroek px = 0;
1633eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
1634eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
1635eda6f593SDavid van Moolenbroek
1636eda6f593SDavid van Moolenbroek while (px < xx) {
1637eda6f593SDavid van Moolenbroek gc = grid_peek_cell(data->backing->grid, px, py);
1638*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1639*0a6a1f1dSLionel Sambuc if (ud.size != 1 || *ud.data != ' ')
1640eda6f593SDavid van Moolenbroek break;
1641eda6f593SDavid van Moolenbroek px++;
1642eda6f593SDavid van Moolenbroek }
1643eda6f593SDavid van Moolenbroek
1644eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1645*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1646eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1647eda6f593SDavid van Moolenbroek }
1648eda6f593SDavid van Moolenbroek
1649eda6f593SDavid van Moolenbroek void
window_copy_cursor_end_of_line(struct window_pane * wp)1650eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(struct window_pane *wp)
1651eda6f593SDavid van Moolenbroek {
1652eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1653eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1654eda6f593SDavid van Moolenbroek struct grid *gd = back_s->grid;
1655eda6f593SDavid van Moolenbroek u_int px, py;
1656eda6f593SDavid van Moolenbroek
1657eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1658eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1659eda6f593SDavid van Moolenbroek
1660eda6f593SDavid van Moolenbroek if (data->cx == px) {
1661eda6f593SDavid van Moolenbroek if (data->screen.sel.flag && data->rectflag)
1662eda6f593SDavid van Moolenbroek px = screen_size_x(back_s);
1663eda6f593SDavid van Moolenbroek if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
1664eda6f593SDavid van Moolenbroek while (py < gd->sy + gd->hsize &&
1665eda6f593SDavid van Moolenbroek gd->linedata[py].flags & GRID_LINE_WRAPPED) {
1666eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
1667eda6f593SDavid van Moolenbroek py = screen_hsize(back_s)
1668eda6f593SDavid van Moolenbroek + data->cy - data->oy;
1669eda6f593SDavid van Moolenbroek }
1670eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1671eda6f593SDavid van Moolenbroek }
1672eda6f593SDavid van Moolenbroek }
1673eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1674eda6f593SDavid van Moolenbroek
1675*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1676eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1677eda6f593SDavid van Moolenbroek }
1678eda6f593SDavid van Moolenbroek
1679eda6f593SDavid van Moolenbroek void
window_copy_other_end(struct window_pane * wp)1680*0a6a1f1dSLionel Sambuc window_copy_other_end(struct window_pane *wp)
1681*0a6a1f1dSLionel Sambuc {
1682*0a6a1f1dSLionel Sambuc struct window_copy_mode_data *data = wp->modedata;
1683*0a6a1f1dSLionel Sambuc struct screen *s = &data->screen;
1684*0a6a1f1dSLionel Sambuc u_int selx, sely, cx, cy, yy;
1685*0a6a1f1dSLionel Sambuc
1686*0a6a1f1dSLionel Sambuc if (!s->sel.flag)
1687*0a6a1f1dSLionel Sambuc return;
1688*0a6a1f1dSLionel Sambuc
1689*0a6a1f1dSLionel Sambuc selx = data->selx;
1690*0a6a1f1dSLionel Sambuc sely = data->sely;
1691*0a6a1f1dSLionel Sambuc cx = data->cx;
1692*0a6a1f1dSLionel Sambuc cy = data->cy;
1693*0a6a1f1dSLionel Sambuc yy = screen_hsize(data->backing) + data->cy - data->oy;
1694*0a6a1f1dSLionel Sambuc
1695*0a6a1f1dSLionel Sambuc data->selx = cx;
1696*0a6a1f1dSLionel Sambuc data->sely = yy;
1697*0a6a1f1dSLionel Sambuc data->cx = selx;
1698*0a6a1f1dSLionel Sambuc
1699*0a6a1f1dSLionel Sambuc if (sely < screen_hsize(data->backing) - data->oy) {
1700*0a6a1f1dSLionel Sambuc data->oy = screen_hsize(data->backing) - sely;
1701*0a6a1f1dSLionel Sambuc data->cy = 0;
1702*0a6a1f1dSLionel Sambuc } else if (sely > screen_hsize(data->backing) - data->oy + screen_size_y(s)) {
1703*0a6a1f1dSLionel Sambuc data->oy = screen_hsize(data->backing) - sely + screen_size_y(s) - 1;
1704*0a6a1f1dSLionel Sambuc data->cy = screen_size_y(s) - 1;
1705*0a6a1f1dSLionel Sambuc
1706*0a6a1f1dSLionel Sambuc } else
1707*0a6a1f1dSLionel Sambuc data->cy = cy + sely - yy;
1708*0a6a1f1dSLionel Sambuc
1709*0a6a1f1dSLionel Sambuc window_copy_redraw_screen(wp);
1710*0a6a1f1dSLionel Sambuc }
1711*0a6a1f1dSLionel Sambuc
1712*0a6a1f1dSLionel Sambuc void
window_copy_cursor_left(struct window_pane * wp)1713eda6f593SDavid van Moolenbroek window_copy_cursor_left(struct window_pane *wp)
1714eda6f593SDavid van Moolenbroek {
1715eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1716eda6f593SDavid van Moolenbroek
1717eda6f593SDavid van Moolenbroek if (data->cx == 0) {
1718eda6f593SDavid van Moolenbroek window_copy_cursor_up(wp, 0);
1719eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(wp);
1720eda6f593SDavid van Moolenbroek } else {
1721eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, data->cx - 1, data->cy);
1722*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1723eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1724eda6f593SDavid van Moolenbroek }
1725eda6f593SDavid van Moolenbroek }
1726eda6f593SDavid van Moolenbroek
1727eda6f593SDavid van Moolenbroek void
window_copy_cursor_right(struct window_pane * wp)1728eda6f593SDavid van Moolenbroek window_copy_cursor_right(struct window_pane *wp)
1729eda6f593SDavid van Moolenbroek {
1730eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1731eda6f593SDavid van Moolenbroek u_int px, py;
1732eda6f593SDavid van Moolenbroek
1733eda6f593SDavid van Moolenbroek if (data->screen.sel.flag && data->rectflag)
1734eda6f593SDavid van Moolenbroek px = screen_size_x(&data->screen);
1735eda6f593SDavid van Moolenbroek else {
1736eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
1737eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1738eda6f593SDavid van Moolenbroek }
1739eda6f593SDavid van Moolenbroek
1740eda6f593SDavid van Moolenbroek if (data->cx >= px) {
1741eda6f593SDavid van Moolenbroek window_copy_cursor_start_of_line(wp);
1742eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
1743eda6f593SDavid van Moolenbroek } else {
1744eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, data->cx + 1, data->cy);
1745*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1746eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1747eda6f593SDavid van Moolenbroek }
1748eda6f593SDavid van Moolenbroek }
1749eda6f593SDavid van Moolenbroek
1750eda6f593SDavid van Moolenbroek void
window_copy_cursor_up(struct window_pane * wp,int scroll_only)1751eda6f593SDavid van Moolenbroek window_copy_cursor_up(struct window_pane *wp, int scroll_only)
1752eda6f593SDavid van Moolenbroek {
1753eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1754eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1755eda6f593SDavid van Moolenbroek u_int ox, oy, px, py;
1756eda6f593SDavid van Moolenbroek
1757eda6f593SDavid van Moolenbroek oy = screen_hsize(data->backing) + data->cy - data->oy;
1758eda6f593SDavid van Moolenbroek ox = window_copy_find_length(wp, oy);
1759*0a6a1f1dSLionel Sambuc if (data->cx != ox) {
1760eda6f593SDavid van Moolenbroek data->lastcx = data->cx;
1761eda6f593SDavid van Moolenbroek data->lastsx = ox;
1762eda6f593SDavid van Moolenbroek }
1763eda6f593SDavid van Moolenbroek
1764eda6f593SDavid van Moolenbroek data->cx = data->lastcx;
1765eda6f593SDavid van Moolenbroek if (scroll_only || data->cy == 0) {
1766eda6f593SDavid van Moolenbroek window_copy_scroll_down(wp, 1);
1767eda6f593SDavid van Moolenbroek if (scroll_only) {
1768eda6f593SDavid van Moolenbroek if (data->cy == screen_size_y(s) - 1)
1769eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1770eda6f593SDavid van Moolenbroek else
1771eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 2);
1772eda6f593SDavid van Moolenbroek }
1773eda6f593SDavid van Moolenbroek } else {
1774eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, data->cx, data->cy - 1);
1775*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1)) {
1776eda6f593SDavid van Moolenbroek if (data->cy == screen_size_y(s) - 1)
1777eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1778eda6f593SDavid van Moolenbroek else
1779eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 2);
1780eda6f593SDavid van Moolenbroek }
1781eda6f593SDavid van Moolenbroek }
1782eda6f593SDavid van Moolenbroek
1783eda6f593SDavid van Moolenbroek if (!data->screen.sel.flag || !data->rectflag) {
1784eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
1785eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1786eda6f593SDavid van Moolenbroek if ((data->cx >= data->lastsx && data->cx != px) ||
1787eda6f593SDavid van Moolenbroek data->cx > px)
1788eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(wp);
1789eda6f593SDavid van Moolenbroek }
1790eda6f593SDavid van Moolenbroek }
1791eda6f593SDavid van Moolenbroek
1792eda6f593SDavid van Moolenbroek void
window_copy_cursor_down(struct window_pane * wp,int scroll_only)1793eda6f593SDavid van Moolenbroek window_copy_cursor_down(struct window_pane *wp, int scroll_only)
1794eda6f593SDavid van Moolenbroek {
1795eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1796eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
1797eda6f593SDavid van Moolenbroek u_int ox, oy, px, py;
1798eda6f593SDavid van Moolenbroek
1799eda6f593SDavid van Moolenbroek oy = screen_hsize(data->backing) + data->cy - data->oy;
1800eda6f593SDavid van Moolenbroek ox = window_copy_find_length(wp, oy);
1801*0a6a1f1dSLionel Sambuc if (data->cx != ox) {
1802eda6f593SDavid van Moolenbroek data->lastcx = data->cx;
1803eda6f593SDavid van Moolenbroek data->lastsx = ox;
1804eda6f593SDavid van Moolenbroek }
1805eda6f593SDavid van Moolenbroek
1806eda6f593SDavid van Moolenbroek data->cx = data->lastcx;
1807eda6f593SDavid van Moolenbroek if (scroll_only || data->cy == screen_size_y(s) - 1) {
1808eda6f593SDavid van Moolenbroek window_copy_scroll_up(wp, 1);
1809eda6f593SDavid van Moolenbroek if (scroll_only && data->cy > 0)
1810eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy - 1, 2);
1811eda6f593SDavid van Moolenbroek } else {
1812eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, data->cx, data->cy + 1);
1813*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1814eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy - 1, 2);
1815eda6f593SDavid van Moolenbroek }
1816eda6f593SDavid van Moolenbroek
1817eda6f593SDavid van Moolenbroek if (!data->screen.sel.flag || !data->rectflag) {
1818eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
1819eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
1820eda6f593SDavid van Moolenbroek if ((data->cx >= data->lastsx && data->cx != px) ||
1821eda6f593SDavid van Moolenbroek data->cx > px)
1822eda6f593SDavid van Moolenbroek window_copy_cursor_end_of_line(wp);
1823eda6f593SDavid van Moolenbroek }
1824eda6f593SDavid van Moolenbroek }
1825eda6f593SDavid van Moolenbroek
1826eda6f593SDavid van Moolenbroek void
window_copy_cursor_jump(struct window_pane * wp)1827eda6f593SDavid van Moolenbroek window_copy_cursor_jump(struct window_pane *wp)
1828eda6f593SDavid van Moolenbroek {
1829eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1830eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1831eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1832*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1833eda6f593SDavid van Moolenbroek u_int px, py, xx;
1834eda6f593SDavid van Moolenbroek
1835eda6f593SDavid van Moolenbroek px = data->cx + 1;
1836eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1837eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
1838eda6f593SDavid van Moolenbroek
1839eda6f593SDavid van Moolenbroek while (px < xx) {
1840eda6f593SDavid van Moolenbroek gc = grid_peek_cell(back_s->grid, px, py);
1841*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1842*0a6a1f1dSLionel Sambuc if (!(gc->flags & GRID_FLAG_PADDING) &&
1843*0a6a1f1dSLionel Sambuc ud.size == 1 && *ud.data == data->jumpchar) {
1844eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1845*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1846eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1847eda6f593SDavid van Moolenbroek return;
1848eda6f593SDavid van Moolenbroek }
1849eda6f593SDavid van Moolenbroek px++;
1850eda6f593SDavid van Moolenbroek }
1851eda6f593SDavid van Moolenbroek }
1852eda6f593SDavid van Moolenbroek
1853eda6f593SDavid van Moolenbroek void
window_copy_cursor_jump_back(struct window_pane * wp)1854eda6f593SDavid van Moolenbroek window_copy_cursor_jump_back(struct window_pane *wp)
1855eda6f593SDavid van Moolenbroek {
1856eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1857eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1858eda6f593SDavid van Moolenbroek const struct grid_cell *gc;
1859*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1860eda6f593SDavid van Moolenbroek u_int px, py;
1861eda6f593SDavid van Moolenbroek
1862eda6f593SDavid van Moolenbroek px = data->cx;
1863eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1864eda6f593SDavid van Moolenbroek
1865eda6f593SDavid van Moolenbroek if (px > 0)
1866eda6f593SDavid van Moolenbroek px--;
1867eda6f593SDavid van Moolenbroek
1868eda6f593SDavid van Moolenbroek for (;;) {
1869eda6f593SDavid van Moolenbroek gc = grid_peek_cell(back_s->grid, px, py);
1870*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1871*0a6a1f1dSLionel Sambuc if (!(gc->flags & GRID_FLAG_PADDING) &&
1872*0a6a1f1dSLionel Sambuc ud.size == 1 && *ud.data == data->jumpchar) {
1873eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1874*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1875*0a6a1f1dSLionel Sambuc window_copy_redraw_lines(wp, data->cy, 1);
1876*0a6a1f1dSLionel Sambuc return;
1877*0a6a1f1dSLionel Sambuc }
1878*0a6a1f1dSLionel Sambuc if (px == 0)
1879*0a6a1f1dSLionel Sambuc break;
1880*0a6a1f1dSLionel Sambuc px--;
1881*0a6a1f1dSLionel Sambuc }
1882*0a6a1f1dSLionel Sambuc }
1883*0a6a1f1dSLionel Sambuc
1884*0a6a1f1dSLionel Sambuc void
window_copy_cursor_jump_to(struct window_pane * wp)1885*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to(struct window_pane *wp)
1886*0a6a1f1dSLionel Sambuc {
1887*0a6a1f1dSLionel Sambuc struct window_copy_mode_data *data = wp->modedata;
1888*0a6a1f1dSLionel Sambuc struct screen *back_s = data->backing;
1889*0a6a1f1dSLionel Sambuc const struct grid_cell *gc;
1890*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1891*0a6a1f1dSLionel Sambuc u_int px, py, xx;
1892*0a6a1f1dSLionel Sambuc
1893*0a6a1f1dSLionel Sambuc px = data->cx + 1;
1894*0a6a1f1dSLionel Sambuc py = screen_hsize(back_s) + data->cy - data->oy;
1895*0a6a1f1dSLionel Sambuc xx = window_copy_find_length(wp, py);
1896*0a6a1f1dSLionel Sambuc
1897*0a6a1f1dSLionel Sambuc while (px < xx) {
1898*0a6a1f1dSLionel Sambuc gc = grid_peek_cell(back_s->grid, px, py);
1899*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1900*0a6a1f1dSLionel Sambuc if (!(gc->flags & GRID_FLAG_PADDING) &&
1901*0a6a1f1dSLionel Sambuc ud.size == 1 && *ud.data == data->jumpchar) {
1902*0a6a1f1dSLionel Sambuc window_copy_update_cursor(wp, px - 1, data->cy);
1903*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1904*0a6a1f1dSLionel Sambuc window_copy_redraw_lines(wp, data->cy, 1);
1905*0a6a1f1dSLionel Sambuc return;
1906*0a6a1f1dSLionel Sambuc }
1907*0a6a1f1dSLionel Sambuc px++;
1908*0a6a1f1dSLionel Sambuc }
1909*0a6a1f1dSLionel Sambuc }
1910*0a6a1f1dSLionel Sambuc
1911*0a6a1f1dSLionel Sambuc void
window_copy_cursor_jump_to_back(struct window_pane * wp)1912*0a6a1f1dSLionel Sambuc window_copy_cursor_jump_to_back(struct window_pane *wp)
1913*0a6a1f1dSLionel Sambuc {
1914*0a6a1f1dSLionel Sambuc struct window_copy_mode_data *data = wp->modedata;
1915*0a6a1f1dSLionel Sambuc struct screen *back_s = data->backing;
1916*0a6a1f1dSLionel Sambuc const struct grid_cell *gc;
1917*0a6a1f1dSLionel Sambuc struct utf8_data ud;
1918*0a6a1f1dSLionel Sambuc u_int px, py;
1919*0a6a1f1dSLionel Sambuc
1920*0a6a1f1dSLionel Sambuc px = data->cx;
1921*0a6a1f1dSLionel Sambuc py = screen_hsize(back_s) + data->cy - data->oy;
1922*0a6a1f1dSLionel Sambuc
1923*0a6a1f1dSLionel Sambuc if (px > 0)
1924*0a6a1f1dSLionel Sambuc px--;
1925*0a6a1f1dSLionel Sambuc
1926*0a6a1f1dSLionel Sambuc for (;;) {
1927*0a6a1f1dSLionel Sambuc gc = grid_peek_cell(back_s->grid, px, py);
1928*0a6a1f1dSLionel Sambuc grid_cell_get(gc, &ud);
1929*0a6a1f1dSLionel Sambuc if (!(gc->flags & GRID_FLAG_PADDING) &&
1930*0a6a1f1dSLionel Sambuc ud.size == 1 && *ud.data == data->jumpchar) {
1931*0a6a1f1dSLionel Sambuc window_copy_update_cursor(wp, px + 1, data->cy);
1932*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1933eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1934eda6f593SDavid van Moolenbroek return;
1935eda6f593SDavid van Moolenbroek }
1936eda6f593SDavid van Moolenbroek if (px == 0)
1937eda6f593SDavid van Moolenbroek break;
1938eda6f593SDavid van Moolenbroek px--;
1939eda6f593SDavid van Moolenbroek }
1940eda6f593SDavid van Moolenbroek }
1941eda6f593SDavid van Moolenbroek
1942eda6f593SDavid van Moolenbroek void
window_copy_cursor_next_word(struct window_pane * wp,const char * separators)1943eda6f593SDavid van Moolenbroek window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
1944eda6f593SDavid van Moolenbroek {
1945eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1946eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1947eda6f593SDavid van Moolenbroek u_int px, py, xx, yy;
1948eda6f593SDavid van Moolenbroek int expected = 0;
1949eda6f593SDavid van Moolenbroek
1950eda6f593SDavid van Moolenbroek px = data->cx;
1951eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1952eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
1953eda6f593SDavid van Moolenbroek yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
1954eda6f593SDavid van Moolenbroek
1955eda6f593SDavid van Moolenbroek /*
1956eda6f593SDavid van Moolenbroek * First skip past any nonword characters and then any word characters.
1957eda6f593SDavid van Moolenbroek *
1958eda6f593SDavid van Moolenbroek * expected is initially set to 0 for the former and then 1 for the
1959eda6f593SDavid van Moolenbroek * latter.
1960eda6f593SDavid van Moolenbroek */
1961eda6f593SDavid van Moolenbroek do {
1962eda6f593SDavid van Moolenbroek while (px > xx ||
1963eda6f593SDavid van Moolenbroek window_copy_in_set(wp, px, py, separators) == expected) {
1964eda6f593SDavid van Moolenbroek /* Move down if we're past the end of the line. */
1965eda6f593SDavid van Moolenbroek if (px > xx) {
1966eda6f593SDavid van Moolenbroek if (py == yy)
1967eda6f593SDavid van Moolenbroek return;
1968eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
1969eda6f593SDavid van Moolenbroek px = 0;
1970eda6f593SDavid van Moolenbroek
1971eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1972eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
1973eda6f593SDavid van Moolenbroek } else
1974eda6f593SDavid van Moolenbroek px++;
1975eda6f593SDavid van Moolenbroek }
1976eda6f593SDavid van Moolenbroek expected = !expected;
1977eda6f593SDavid van Moolenbroek } while (expected == 1);
1978eda6f593SDavid van Moolenbroek
1979eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
1980*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
1981eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
1982eda6f593SDavid van Moolenbroek }
1983eda6f593SDavid van Moolenbroek
1984eda6f593SDavid van Moolenbroek void
window_copy_cursor_next_word_end(struct window_pane * wp,const char * separators)1985eda6f593SDavid van Moolenbroek window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
1986eda6f593SDavid van Moolenbroek {
1987eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
1988*0a6a1f1dSLionel Sambuc struct options *oo = &wp->window->options;
1989eda6f593SDavid van Moolenbroek struct screen *back_s = data->backing;
1990eda6f593SDavid van Moolenbroek u_int px, py, xx, yy;
1991*0a6a1f1dSLionel Sambuc int keys, expected = 1;
1992eda6f593SDavid van Moolenbroek
1993eda6f593SDavid van Moolenbroek px = data->cx;
1994eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
1995eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
1996eda6f593SDavid van Moolenbroek yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
1997eda6f593SDavid van Moolenbroek
1998*0a6a1f1dSLionel Sambuc keys = options_get_number(oo, "mode-keys");
1999*0a6a1f1dSLionel Sambuc if (keys == MODEKEY_VI && !window_copy_in_set(wp, px, py, separators))
2000*0a6a1f1dSLionel Sambuc px++;
2001*0a6a1f1dSLionel Sambuc
2002eda6f593SDavid van Moolenbroek /*
2003eda6f593SDavid van Moolenbroek * First skip past any word characters, then any nonword characters.
2004eda6f593SDavid van Moolenbroek *
2005eda6f593SDavid van Moolenbroek * expected is initially set to 1 for the former and then 0 for the
2006eda6f593SDavid van Moolenbroek * latter.
2007eda6f593SDavid van Moolenbroek */
2008eda6f593SDavid van Moolenbroek do {
2009eda6f593SDavid van Moolenbroek while (px > xx ||
2010eda6f593SDavid van Moolenbroek window_copy_in_set(wp, px, py, separators) == expected) {
2011eda6f593SDavid van Moolenbroek /* Move down if we're past the end of the line. */
2012eda6f593SDavid van Moolenbroek if (px > xx) {
2013eda6f593SDavid van Moolenbroek if (py == yy)
2014eda6f593SDavid van Moolenbroek return;
2015eda6f593SDavid van Moolenbroek window_copy_cursor_down(wp, 0);
2016eda6f593SDavid van Moolenbroek px = 0;
2017eda6f593SDavid van Moolenbroek
2018eda6f593SDavid van Moolenbroek py = screen_hsize(back_s) + data->cy - data->oy;
2019eda6f593SDavid van Moolenbroek xx = window_copy_find_length(wp, py);
2020eda6f593SDavid van Moolenbroek } else
2021eda6f593SDavid van Moolenbroek px++;
2022eda6f593SDavid van Moolenbroek }
2023eda6f593SDavid van Moolenbroek expected = !expected;
2024eda6f593SDavid van Moolenbroek } while (expected == 0);
2025eda6f593SDavid van Moolenbroek
2026*0a6a1f1dSLionel Sambuc if (keys == MODEKEY_VI && px != 0)
2027*0a6a1f1dSLionel Sambuc px--;
2028*0a6a1f1dSLionel Sambuc
2029eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
2030*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
2031eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
2032eda6f593SDavid van Moolenbroek }
2033eda6f593SDavid van Moolenbroek
2034eda6f593SDavid van Moolenbroek /* Move to the previous place where a word begins. */
2035eda6f593SDavid van Moolenbroek void
window_copy_cursor_previous_word(struct window_pane * wp,const char * separators)2036eda6f593SDavid van Moolenbroek window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
2037eda6f593SDavid van Moolenbroek {
2038eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
2039eda6f593SDavid van Moolenbroek u_int px, py;
2040eda6f593SDavid van Moolenbroek
2041eda6f593SDavid van Moolenbroek px = data->cx;
2042eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
2043eda6f593SDavid van Moolenbroek
2044eda6f593SDavid van Moolenbroek /* Move back to the previous word character. */
2045eda6f593SDavid van Moolenbroek for (;;) {
2046eda6f593SDavid van Moolenbroek if (px > 0) {
2047eda6f593SDavid van Moolenbroek px--;
2048eda6f593SDavid van Moolenbroek if (!window_copy_in_set(wp, px, py, separators))
2049eda6f593SDavid van Moolenbroek break;
2050eda6f593SDavid van Moolenbroek } else {
2051eda6f593SDavid van Moolenbroek if (data->cy == 0 &&
2052eda6f593SDavid van Moolenbroek (screen_hsize(data->backing) == 0 ||
2053eda6f593SDavid van Moolenbroek data->oy >= screen_hsize(data->backing) - 1))
2054eda6f593SDavid van Moolenbroek goto out;
2055eda6f593SDavid van Moolenbroek window_copy_cursor_up(wp, 0);
2056eda6f593SDavid van Moolenbroek
2057eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
2058eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
2059eda6f593SDavid van Moolenbroek }
2060eda6f593SDavid van Moolenbroek }
2061eda6f593SDavid van Moolenbroek
2062eda6f593SDavid van Moolenbroek /* Move back to the beginning of this word. */
2063eda6f593SDavid van Moolenbroek while (px > 0 && !window_copy_in_set(wp, px - 1, py, separators))
2064eda6f593SDavid van Moolenbroek px--;
2065eda6f593SDavid van Moolenbroek
2066eda6f593SDavid van Moolenbroek out:
2067eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
2068*0a6a1f1dSLionel Sambuc if (window_copy_update_selection(wp, 1))
2069eda6f593SDavid van Moolenbroek window_copy_redraw_lines(wp, data->cy, 1);
2070eda6f593SDavid van Moolenbroek }
2071eda6f593SDavid van Moolenbroek
2072eda6f593SDavid van Moolenbroek void
window_copy_scroll_up(struct window_pane * wp,u_int ny)2073eda6f593SDavid van Moolenbroek window_copy_scroll_up(struct window_pane *wp, u_int ny)
2074eda6f593SDavid van Moolenbroek {
2075eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
2076eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
2077eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
2078eda6f593SDavid van Moolenbroek
2079eda6f593SDavid van Moolenbroek if (data->oy < ny)
2080eda6f593SDavid van Moolenbroek ny = data->oy;
2081eda6f593SDavid van Moolenbroek if (ny == 0)
2082eda6f593SDavid van Moolenbroek return;
2083eda6f593SDavid van Moolenbroek data->oy -= ny;
2084eda6f593SDavid van Moolenbroek
2085*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 0);
2086*0a6a1f1dSLionel Sambuc
2087eda6f593SDavid van Moolenbroek screen_write_start(&ctx, wp, NULL);
2088eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, 0, 0);
2089eda6f593SDavid van Moolenbroek screen_write_deleteline(&ctx, ny);
2090eda6f593SDavid van Moolenbroek window_copy_write_lines(wp, &ctx, screen_size_y(s) - ny, ny);
2091eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, 0);
2092eda6f593SDavid van Moolenbroek if (screen_size_y(s) > 1)
2093eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, 1);
2094eda6f593SDavid van Moolenbroek if (screen_size_y(s) > 3)
2095eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, screen_size_y(s) - 2);
2096*0a6a1f1dSLionel Sambuc if (s->sel.flag && screen_size_y(s) > ny)
2097eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
2098eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, data->cx, data->cy);
2099eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
2100eda6f593SDavid van Moolenbroek }
2101eda6f593SDavid van Moolenbroek
2102eda6f593SDavid van Moolenbroek void
window_copy_scroll_down(struct window_pane * wp,u_int ny)2103eda6f593SDavid van Moolenbroek window_copy_scroll_down(struct window_pane *wp, u_int ny)
2104eda6f593SDavid van Moolenbroek {
2105eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
2106eda6f593SDavid van Moolenbroek struct screen *s = &data->screen;
2107eda6f593SDavid van Moolenbroek struct screen_write_ctx ctx;
2108eda6f593SDavid van Moolenbroek
2109eda6f593SDavid van Moolenbroek if (ny > screen_hsize(data->backing))
2110eda6f593SDavid van Moolenbroek return;
2111eda6f593SDavid van Moolenbroek
2112eda6f593SDavid van Moolenbroek if (data->oy > screen_hsize(data->backing) - ny)
2113eda6f593SDavid van Moolenbroek ny = screen_hsize(data->backing) - data->oy;
2114eda6f593SDavid van Moolenbroek if (ny == 0)
2115eda6f593SDavid van Moolenbroek return;
2116eda6f593SDavid van Moolenbroek data->oy += ny;
2117eda6f593SDavid van Moolenbroek
2118*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 0);
2119*0a6a1f1dSLionel Sambuc
2120eda6f593SDavid van Moolenbroek screen_write_start(&ctx, wp, NULL);
2121eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, 0, 0);
2122eda6f593SDavid van Moolenbroek screen_write_insertline(&ctx, ny);
2123eda6f593SDavid van Moolenbroek window_copy_write_lines(wp, &ctx, 0, ny);
2124*0a6a1f1dSLionel Sambuc if (s->sel.flag && screen_size_y(s) > ny)
2125eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, ny);
2126*0a6a1f1dSLionel Sambuc else if (ny == 1) /* nuke position */
2127eda6f593SDavid van Moolenbroek window_copy_write_line(wp, &ctx, 1);
2128eda6f593SDavid van Moolenbroek screen_write_cursormove(&ctx, data->cx, data->cy);
2129eda6f593SDavid van Moolenbroek screen_write_stop(&ctx);
2130eda6f593SDavid van Moolenbroek }
2131eda6f593SDavid van Moolenbroek
2132eda6f593SDavid van Moolenbroek void
window_copy_rectangle_toggle(struct window_pane * wp)2133eda6f593SDavid van Moolenbroek window_copy_rectangle_toggle(struct window_pane *wp)
2134eda6f593SDavid van Moolenbroek {
2135eda6f593SDavid van Moolenbroek struct window_copy_mode_data *data = wp->modedata;
2136eda6f593SDavid van Moolenbroek u_int px, py;
2137eda6f593SDavid van Moolenbroek
2138eda6f593SDavid van Moolenbroek data->rectflag = !data->rectflag;
2139eda6f593SDavid van Moolenbroek
2140eda6f593SDavid van Moolenbroek py = screen_hsize(data->backing) + data->cy - data->oy;
2141eda6f593SDavid van Moolenbroek px = window_copy_find_length(wp, py);
2142eda6f593SDavid van Moolenbroek if (data->cx > px)
2143eda6f593SDavid van Moolenbroek window_copy_update_cursor(wp, px, data->cy);
2144eda6f593SDavid van Moolenbroek
2145*0a6a1f1dSLionel Sambuc window_copy_update_selection(wp, 1);
2146eda6f593SDavid van Moolenbroek window_copy_redraw_screen(wp);
2147eda6f593SDavid van Moolenbroek }
2148