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