From bbab5b7a30717c4455f7725e6adc364f6c274e7d Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 10 Nov 2020 08:16:52 +0000 Subject: Allow previous-word to scroll onto the first line, noticed by Anindya Mukherjee. --- window-copy.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 1dc0c293..6dc03b34 100644 --- a/window-copy.c +++ b/window-copy.c @@ -4526,10 +4526,11 @@ window_copy_cursor_previous_word_pos(struct window_mode_entry *wme, const char *separators, int already, u_int *ppx, u_int *ppy) { struct window_copy_mode_data *data = wme->data; - u_int px, py; + u_int px, py, hsize; + hsize = screen_hsize(data->backing); px = data->cx; - py = screen_hsize(data->backing) + data->cy - data->oy; + py = hsize + data->cy - data->oy; /* Move back to the previous word character. */ if (already || window_copy_in_set(wme, px, py, separators)) { @@ -4542,9 +4543,7 @@ window_copy_cursor_previous_word_pos(struct window_mode_entry *wme, } else { if (py == 0 || (data->cy == 0 && - (screen_hsize(data->backing) == 0 || - data->oy >= - screen_hsize(data->backing) - 1))) + (hsize == 0 || data->oy > hsize - 1))) goto out; py--; @@ -4573,10 +4572,11 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, const char *separators, int already) { struct window_copy_mode_data *data = wme->data; - u_int px, py; + u_int px, py, hsize; + hsize = screen_hsize(data->backing); px = data->cx; - py = screen_hsize(data->backing) + data->cy - data->oy; + py = hsize + data->cy - data->oy; /* Move back to the previous word character. */ if (already || window_copy_in_set(wme, px, py, separators)) { @@ -4588,14 +4588,11 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, break; } else { if (data->cy == 0 && - (screen_hsize(data->backing) == 0 || - data->oy >= - screen_hsize(data->backing) - 1)) + (hsize == 0 || data->oy > hsize - 1)) goto out; window_copy_cursor_up(wme, 0); - py = screen_hsize(data->backing) + data->cy - - data->oy; + py = hsize + data->cy - data->oy; px = window_copy_find_length(wme, py); /* Stop if separator at EOL. */ -- cgit From c43f2dce1b0ca64b43f7614d4da52bc9f2c195fe Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 22 Dec 2020 09:22:14 +0000 Subject: Break cursor movement in grid into a common set of functions that can handle line wrapping and so on in one place and use them for the obvious copy mode commands. From Anindya Mukherjee. --- window-copy.c | 333 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 189 insertions(+), 144 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 6dc03b34..764f6b5b 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3993,18 +3993,31 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid *gd = back_s->grid; - u_int py; - - if (data->cx == 0 && data->lineflag == LINE_SEL_NONE) { - py = screen_hsize(back_s) + data->cy - data->oy; - while (py > 0 && - grid_get_line(gd, py - 1)->flags & GRID_LINE_WRAPPED) { - window_copy_cursor_up(wme, 0); - py = screen_hsize(back_s) + data->cy - data->oy; - } + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; + + px = data->cx; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + + grid_reader_start(&gr, back_s->grid, px, py); + grid_reader_cursor_start_of_line(&gr, 1); + grid_reader_get_cursor(&gr, &px, &py); + + /* Scroll up if we went off the visible screen. */ + yy = hsize - data->oy; + if (py < yy) { + ny = yy - py; + cy = 0; + } else { + ny = 0; + cy = py - yy; + } + while (ny > 0) { + window_copy_cursor_up(wme, 1); + ny--; } - window_copy_update_cursor(wme, 0, data->cy); + window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) window_copy_redraw_lines(wme, data->cy, 1); } @@ -4037,30 +4050,35 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid *gd = back_s->grid; - struct grid_line *gl; - u_int px, py; + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; - py = screen_hsize(back_s) + data->cy - data->oy; - px = window_copy_find_length(wme, py); + px = data->cx; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; - if (data->cx == px && data->lineflag == LINE_SEL_NONE) { - if (data->screen.sel != NULL && data->rectflag) - px = screen_size_x(back_s); - gl = grid_get_line(gd, py); - if (gl->flags & GRID_LINE_WRAPPED) { - while (py < gd->sy + gd->hsize) { - gl = grid_get_line(gd, py); - if (~gl->flags & GRID_LINE_WRAPPED) - break; - window_copy_cursor_down(wme, 0); - py = screen_hsize(back_s) + data->cy - data->oy; - } - px = window_copy_find_length(wme, py); - } + grid_reader_start(&gr, back_s->grid, px, py); + if (data->screen.sel != NULL && data->rectflag) + grid_reader_cursor_end_of_line(&gr, 1, 1); + else + grid_reader_cursor_end_of_line(&gr, 1, 0); + grid_reader_get_cursor(&gr, &px, &py); + + /* Scroll down if we went off the visible screen. */ + cy = py - hsize + data->oy; + yy = screen_size_y(back_s) - 1; + if (cy > yy) + ny = cy - yy; + else + ny = 0; + while (ny > 0) { + window_copy_cursor_down(wme, 1); + ny--; } - window_copy_update_cursor(wme, px, data->cy); - + if (cy > yy) + window_copy_update_cursor(wme, px, yy); + else + window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) window_copy_redraw_lines(wme, data->cy, 1); } @@ -4120,57 +4138,69 @@ static void window_copy_cursor_left(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; - u_int py, cx; - struct grid_cell gc; + struct screen *back_s = data->backing; + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; - py = screen_hsize(data->backing) + data->cy - data->oy; - cx = data->cx; - while (cx > 0) { - grid_get_cell(data->backing->grid, cx, py, &gc); - if (~gc.flags & GRID_FLAG_PADDING) - break; - cx--; + px = data->cx; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + + grid_reader_start(&gr, back_s->grid, px, py); + grid_reader_cursor_left(&gr); + grid_reader_get_cursor(&gr, &px, &py); + + /* Scroll up if we went off the visible screen. */ + yy = hsize - data->oy; + if (py < yy) { + ny = yy - py; + cy = 0; + } else { + ny = 0; + cy = py - yy; } - if (cx == 0 && py > 0) { - window_copy_cursor_up(wme, 0); - window_copy_cursor_end_of_line(wme); - } else if (cx > 0) { - window_copy_update_cursor(wme, cx - 1, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + while (ny > 0) { + window_copy_cursor_up(wme, 1); + ny--; } + window_copy_update_cursor(wme, px, cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); } static void window_copy_cursor_right(struct window_mode_entry *wme, int all) { struct window_copy_mode_data *data = wme->data; - u_int px, py, yy, cx, cy; - struct grid_cell gc; + struct screen *back_s = data->backing; + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; - py = screen_hsize(data->backing) + data->cy - data->oy; - yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1; - if (all || (data->screen.sel != NULL && data->rectflag)) - px = screen_size_x(&data->screen); - else - px = window_copy_find_length(wme, py); + px = data->cx; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; - if (data->cx >= px && py < yy) { - window_copy_cursor_start_of_line(wme); - window_copy_cursor_down(wme, 0); - } else if (data->cx < px) { - cx = data->cx + 1; - cy = screen_hsize(data->backing) + data->cy - data->oy; - while (cx < px) { - grid_get_cell(data->backing->grid, cx, cy, &gc); - if (~gc.flags & GRID_FLAG_PADDING) - break; - cx++; - } - window_copy_update_cursor(wme, cx, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + grid_reader_start(&gr, back_s->grid, px, py); + grid_reader_cursor_right(&gr, 1, all); + grid_reader_get_cursor(&gr, &px, &py); + + /* Scroll down if we went off the visible screen. */ + cy = py - hsize + data->oy; + yy = screen_size_y(back_s) - 1; + if (cy > yy) + ny = cy - yy; + else + ny = 0; + while (ny > 0) { + window_copy_cursor_down(wme, 1); + ny--; } + if (cy > yy) + window_copy_update_cursor(wme, px, yy); + else + window_copy_update_cursor(wme, px, cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); } static void @@ -4214,13 +4244,30 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only) px = window_copy_find_length(wme, py); if ((data->cx >= data->lastsx && data->cx != px) || data->cx > px) - window_copy_cursor_end_of_line(wme); + { + window_copy_update_cursor(wme, px, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } } if (data->lineflag == LINE_SEL_LEFT_RIGHT) - window_copy_cursor_end_of_line(wme); + { + py = screen_hsize(data->backing) + data->cy - data->oy; + if (data->rectflag) + px = screen_size_x(data->backing); + else + px = window_copy_find_length(wme, py); + window_copy_update_cursor(wme, px, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } else if (data->lineflag == LINE_SEL_RIGHT_LEFT) - window_copy_cursor_start_of_line(wme); + { + window_copy_update_cursor(wme, 0, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } } static void @@ -4256,13 +4303,30 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only) px = window_copy_find_length(wme, py); if ((data->cx >= data->lastsx && data->cx != px) || data->cx > px) - window_copy_cursor_end_of_line(wme); + { + window_copy_update_cursor(wme, px, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } } if (data->lineflag == LINE_SEL_LEFT_RIGHT) - window_copy_cursor_end_of_line(wme); + { + py = screen_hsize(data->backing) + data->cy - data->oy; + if (data->rectflag) + px = screen_size_x(data->backing); + else + px = window_copy_find_length(wme, py); + window_copy_update_cursor(wme, px, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } else if (data->lineflag == LINE_SEL_RIGHT_LEFT) - window_copy_cursor_start_of_line(wme); + { + window_copy_update_cursor(wme, 0, data->cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, data->cy, 1); + } } static void @@ -4476,46 +4540,38 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, struct window_copy_mode_data *data = wme->data; struct options *oo = wp->window->options; struct screen *back_s = data->backing; - u_int px, py, xx, yy; - int keys, expected = 1; + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; + int keys; px = data->cx; - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); - yy = screen_hsize(back_s) + screen_size_y(back_s) - 1; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + grid_reader_start(&gr, back_s->grid, px, py); keys = options_get_number(oo, "mode-keys"); - if (keys == MODEKEY_VI && !window_copy_in_set(wme, px, py, separators)) - px++; - - /* - * First skip past any word characters, then any nonword characters. - * - * expected is initially set to 1 for the former and then 0 for the - * latter. - */ - do { - while (px > xx || - window_copy_in_set(wme, px, py, separators) == expected) { - /* Move down if we're past the end of the line. */ - if (px > xx) { - if (py == yy) - return; - window_copy_cursor_down(wme, 0); - px = 0; - - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); - } else - px++; - } - expected = !expected; - } while (expected == 0); - - if (keys == MODEKEY_VI && px != 0) - px--; - - window_copy_update_cursor(wme, px, data->cy); + if (keys == MODEKEY_VI && !grid_reader_in_set(&gr, separators)) + grid_reader_cursor_right(&gr, 0, 0); + grid_reader_cursor_next_word_end(&gr, separators); + if (keys == MODEKEY_VI) + grid_reader_cursor_left(&gr); + grid_reader_get_cursor(&gr, &px, &py); + + /* Scroll down if we went off the visible screen. */ + cy = py - hsize + data->oy; + yy = screen_size_y(back_s) - 1; + if (cy > yy) + ny = cy - yy; + else + ny = 0; + while (ny > 0) { + window_copy_cursor_down(wme, 1); + ny--; + } + if (cy > yy) + window_copy_update_cursor(wme, px, yy); + else + window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, no_reset)) window_copy_redraw_lines(wme, data->cy, 1); } @@ -4572,43 +4628,32 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, const char *separators, int already) { struct window_copy_mode_data *data = wme->data; - u_int px, py, hsize; + struct screen *back_s = data->backing; + struct grid_reader gr; + u_int px, py, cy, yy, ny, hsize; - hsize = screen_hsize(data->backing); px = data->cx; + hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; - /* Move back to the previous word character. */ - if (already || window_copy_in_set(wme, px, py, separators)) { - for (;;) { - if (px > 0) { - px--; - if (!window_copy_in_set(wme, px, py, - separators)) - break; - } else { - if (data->cy == 0 && - (hsize == 0 || data->oy > hsize - 1)) - goto out; - window_copy_cursor_up(wme, 0); - - py = hsize + data->cy - data->oy; - px = window_copy_find_length(wme, py); + grid_reader_start(&gr, back_s->grid, px, py); + grid_reader_cursor_previous_word(&gr, separators, already); + grid_reader_get_cursor(&gr, &px, &py); - /* Stop if separator at EOL. */ - if (px > 0 && window_copy_in_set(wme, px - 1, - py, separators)) - break; - } - } + /* Scroll up if we went off the visible screen. */ + yy = hsize - data->oy; + if (py < yy) { + ny = yy - py; + cy = 0; + } else { + ny = 0; + cy = py - yy; } - - /* Move back to the beginning of this word. */ - while (px > 0 && !window_copy_in_set(wme, px - 1, py, separators)) - px--; - -out: - window_copy_update_cursor(wme, px, data->cy); + while (ny > 0) { + window_copy_cursor_up(wme, 1); + ny--; + } + window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) window_copy_redraw_lines(wme, data->cy, 1); } -- cgit From c68baaad98807963da954bc1aa77c22f2df05ff0 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 28 Dec 2020 09:36:26 +0000 Subject: Remove current match indicator which can't work anymore since we only search the visible region. From Anindya Mukherjee, GitHub issue 2508. --- window-copy.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 764f6b5b..d6af397f 100644 --- a/window-copy.c +++ b/window-copy.c @@ -272,7 +272,7 @@ struct window_copy_mode_data { u_char *searchmark; int searchcount; int searchmore; - int searchthis; + int searchall; int searchx; int searchy; int searcho; @@ -396,6 +396,7 @@ window_copy_common_init(struct window_mode_entry *wme) data->searchstr = NULL; } data->searchx = data->searchy = data->searcho = -1; + data->searchall = 1; data->jumptype = WINDOW_COPY_OFF; data->jumpchar = '\0'; @@ -2334,9 +2335,6 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, if (clear != WINDOW_COPY_CMD_CLEAR_NEVER) { window_copy_clear_marks(wme); data->searchx = data->searchy = -1; - } else if (data->searchthis != -1) { - data->searchthis = -1; - action = WINDOW_COPY_CMD_REDRAW; } if (action == WINDOW_COPY_CMD_NOTHING) action = WINDOW_COPY_CMD_REDRAW; @@ -2929,9 +2927,11 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex, if (data->timeout) return (0); - if (wp->searchstr == NULL || wp->searchregex != regex) + if (data->searchall || wp->searchstr == NULL || + wp->searchregex != regex) { visible_only = 0; - else + data->searchall = 0; + } else visible_only = (strcmp(wp->searchstr, str) == 0); free(wp->searchstr); wp->searchstr = xstrdup(str); @@ -3116,7 +3116,6 @@ again: if (!visible_only) { if (stopped) { - data->searchthis = -1; if (nfound > 1000) data->searchcount = 1000; else if (nfound > 100) @@ -3127,10 +3126,6 @@ again: data->searchcount = -1; data->searchmore = 1; } else { - if (which != -1) - data->searchthis = 1 + nfound - which; - else - data->searchthis = -1; data->searchcount = nfound; data->searchmore = 0; } @@ -3366,15 +3361,11 @@ window_copy_write_line(struct window_mode_entry *wme, if (data->searchcount == -1) { size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->oy, hsize); - } else if (data->searchthis == -1) { + } else { size = xsnprintf(hdr, sizeof hdr, "(%d%s results) [%u/%u]", data->searchcount, data->searchmore ? "+" : "", data->oy, hsize); - } else { - size = xsnprintf(hdr, sizeof hdr, - "(%d/%d results) [%u/%u]", data->searchthis, - data->searchcount, data->oy, hsize); } } if (size > screen_size_x(s)) -- cgit From ccb8b9eb2a32fef1c28d45147ccc8a3ff10e656c Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 6 Jan 2021 07:29:49 +0000 Subject: Remove unused variable, from Ben Boeckel. --- window-copy.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index d6af397f..4c81cb1f 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3009,7 +3009,7 @@ window_copy_search_marks(struct window_mode_entry *wme, struct screen *ssp, struct screen *s = data->backing, ss; struct screen_write_ctx ctx; struct grid *gd = s->grid; - int found, cis, which = -1, stopped = 0; + int found, cis, stopped = 0; int cflags = REG_EXTENDED; u_int px, py, i, b, nfound = 0, width; u_int ssize = 1, start, end; @@ -3072,11 +3072,7 @@ again: if (!found) break; } - nfound++; - if (px == data->cx && - py == gd->hsize + data->cy - data->oy) - which = nfound; if (window_copy_search_mark_at(data, px, py, &b) == 0) { if (b + width > gd->sx * gd->sy) @@ -3088,7 +3084,6 @@ again: else data->searchgen++; } - px += width; } -- cgit From b96c5e3687d36cea7b575a7e151326f1b82824d2 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 8 Jan 2021 08:22:10 +0000 Subject: With incremental search, start empty and only repeat the previous search if the user tries to search again with an empty prompt. This matches emacs behaviour more closely. --- window-copy.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 4c81cb1f..bfa94aed 100644 --- a/window-copy.c +++ b/window-copy.c @@ -2030,6 +2030,8 @@ window_copy_cmd_search_backward_incremental(struct window_copy_cmd_state *cs) data->timeout = 0; + log_debug ("%s: %s", __func__, argument); + prefix = *argument++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; @@ -2083,6 +2085,8 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs) data->timeout = 0; + log_debug ("%s: %s", __func__, argument); + prefix = *argument++; if (data->searchx == -1 || data->searchy == -1) { data->searchx = data->cx; -- cgit From 0730dce5abf5e43f8e3820a1d4e8754e61874a3d Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 18 Jan 2021 11:14:23 +0000 Subject: Hide some warnings on newer GCC versions, GitHUb issue 2525. --- window-copy.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index bfa94aed..889a536d 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3453,10 +3453,10 @@ window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin, struct window_copy_mode_data *data = wme->data; u_int xx, yy; + xx = data->cx; yy = screen_hsize(data->backing) + data->cy - data->oy; switch (data->selflag) { case SEL_WORD: - xx = data->cx; if (no_reset) break; begin = 0; @@ -3482,10 +3482,8 @@ window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin, } break; case SEL_LINE: - if (no_reset) { - xx = data->cx; + if (no_reset) break; - } begin = 0; if (data->dy > yy) { /* Right to left selection. */ @@ -3505,7 +3503,6 @@ window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin, } break; case SEL_CHAR: - xx = data->cx; break; } if (begin) { @@ -4784,22 +4781,22 @@ window_copy_start_drag(struct client *c, struct mouse_event *m) if (x < data->selrx || x > data->endselrx || yg != data->selry) data->selflag = SEL_CHAR; switch (data->selflag) { - case SEL_WORD: - if (data->ws != NULL) { - window_copy_update_cursor(wme, x, y); - window_copy_cursor_previous_word_pos(wme, - data->ws, 0, &x, &y); - y -= screen_hsize(data->backing) - data->oy; - } - window_copy_update_cursor(wme, x, y); - break; - case SEL_LINE: - window_copy_update_cursor(wme, 0, y); - break; - case SEL_CHAR: + case SEL_WORD: + if (data->ws != NULL) { window_copy_update_cursor(wme, x, y); - window_copy_start_selection(wme); - break; + window_copy_cursor_previous_word_pos(wme, data->ws, 0, + &x, &y); + y -= screen_hsize(data->backing) - data->oy; + } + window_copy_update_cursor(wme, x, y); + break; + case SEL_LINE: + window_copy_update_cursor(wme, 0, y); + break; + case SEL_CHAR: + window_copy_update_cursor(wme, x, y); + window_copy_start_selection(wme); + break; } window_copy_redraw_screen(wme); -- cgit From 8d185395e479d8e7792a56bc61415bef640cf4b7 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 22 Jan 2021 10:21:24 +0000 Subject: Fix some cursor movement commands, from Anindya Mukherjee. --- window-copy.c | 98 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 42 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 889a536d..a2f4b2e5 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3981,11 +3981,12 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, cy, oldy, yy, ny, nd, hsize; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_start_of_line(&gr, 1); @@ -3996,9 +3997,11 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) if (py < yy) { ny = yy - py; cy = 0; + nd = 1; } else { ny = 0; cy = py - yy; + nd = oldy - cy + 1; } while (ny > 0) { window_copy_cursor_up(wme, 1); @@ -4006,7 +4009,7 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) } window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_redraw_lines(wme, data->cy, nd); } static void @@ -4038,11 +4041,12 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, cy, oldy, yy, ny, nd, hsize; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); if (data->screen.sel != NULL && data->rectflag) @@ -4054,10 +4058,14 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) /* Scroll down if we went off the visible screen. */ cy = py - hsize + data->oy; yy = screen_size_y(back_s) - 1; - if (cy > yy) + if (cy > yy) { ny = cy - yy; - else + oldy = yy; + nd = 1; + } else { ny = 0; + nd = cy - oldy + 1; + } while (ny > 0) { window_copy_cursor_down(wme, 1); ny--; @@ -4067,7 +4075,7 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) else window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_redraw_lines(wme, oldy, nd); } static void @@ -4433,41 +4441,39 @@ window_copy_cursor_next_word(struct window_mode_entry *wme, { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - u_int px, py, xx, yy; - int expected = 0; + struct grid_reader gr; + u_int px, py, cy, oldy, yy, ny, nd, hsize; px = data->cx; - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); - yy = screen_hsize(back_s) + screen_size_y(back_s) - 1; - - /* - * First skip past any nonword characters and then any word characters. - * - * expected is initially set to 0 for the former and then 1 for the - * latter. - */ - do { - while (px > xx || - window_copy_in_set(wme, px, py, separators) == expected) { - /* Move down if we're past the end of the line. */ - if (px > xx) { - if (py == yy) - return; - window_copy_cursor_down(wme, 0); - px = 0; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + oldy = data->cy; - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); - } else - px++; - } - expected = !expected; - } while (expected == 1); + grid_reader_start(&gr, back_s->grid, px, py); + grid_reader_cursor_next_word(&gr, separators); + grid_reader_get_cursor(&gr, &px, &py); - window_copy_update_cursor(wme, px, data->cy); + /* Scroll down if we went off the visible screen. */ + cy = py - hsize + data->oy; + yy = screen_size_y(back_s) - 1; + if (cy > yy) { + ny = cy - yy; + oldy = yy; + nd = 1; + } else { + ny = 0; + nd = cy - oldy + 1; + } + while (ny > 0) { + window_copy_cursor_down(wme, 1); + ny--; + } + if (cy > yy) + window_copy_update_cursor(wme, px, yy); + else + window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_redraw_lines(wme, oldy, nd); } static void @@ -4528,12 +4534,13 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, struct options *oo = wp->window->options; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, cy, oldy, yy, ny, nd, hsize; int keys; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); keys = options_get_number(oo, "mode-keys"); @@ -4547,10 +4554,14 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, /* Scroll down if we went off the visible screen. */ cy = py - hsize + data->oy; yy = screen_size_y(back_s) - 1; - if (cy > yy) + if (cy > yy) { ny = cy - yy; - else + oldy = yy; + nd = 1; + } else { ny = 0; + nd = cy - oldy + 1; + } while (ny > 0) { window_copy_cursor_down(wme, 1); ny--; @@ -4560,7 +4571,7 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, else window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, no_reset)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_redraw_lines(wme, oldy, nd); } /* Compute the previous place where a word begins. */ @@ -4617,11 +4628,12 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, cy, oldy, yy, ny, nd, hsize; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_previous_word(&gr, separators, already); @@ -4632,9 +4644,11 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, if (py < yy) { ny = yy - py; cy = 0; + nd = 1; } else { ny = 0; cy = py - yy; + nd = oldy - cy + 1; } while (ny > 0) { window_copy_cursor_up(wme, 1); @@ -4642,7 +4656,7 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, } window_copy_update_cursor(wme, px, cy); if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_redraw_lines(wme, data->cy, nd); } static void -- cgit From bba71f696f49cdd3f70eaea12fd3a34c407a5aa3 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 22 Jan 2021 10:24:52 +0000 Subject: Add rectangle-on and rectangle-off copy mode commands, GitHub isse 2546 from author at will dot party. --- window-copy.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index a2f4b2e5..89b2a9af 100644 --- a/window-copy.c +++ b/window-copy.c @@ -128,7 +128,7 @@ static void window_copy_cursor_previous_word(struct window_mode_entry *, const char *, int); static void window_copy_scroll_up(struct window_mode_entry *, u_int); static void window_copy_scroll_down(struct window_mode_entry *, u_int); -static void window_copy_rectangle_toggle(struct window_mode_entry *); +static void window_copy_rectangle_set(struct window_mode_entry *, int); static void window_copy_move_mouse(struct mouse_event *); static void window_copy_drag_update(struct client *, struct mouse_event *); static void window_copy_drag_release(struct client *, struct mouse_event *); @@ -1625,6 +1625,30 @@ window_copy_cmd_previous_word(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_NOTHING); } +static enum window_copy_cmd_action +window_copy_cmd_rectangle_on(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_copy_mode_data *data = wme->data; + + data->lineflag = LINE_SEL_NONE; + window_copy_rectangle_set(wme, 1); + + return (WINDOW_COPY_CMD_NOTHING); +} + +static enum window_copy_cmd_action +window_copy_cmd_rectangle_off(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct window_copy_mode_data *data = wme->data; + + data->lineflag = LINE_SEL_NONE; + window_copy_rectangle_set(wme, 0); + + return (WINDOW_COPY_CMD_NOTHING); +} + static enum window_copy_cmd_action window_copy_cmd_rectangle_toggle(struct window_copy_cmd_state *cs) { @@ -1632,7 +1656,7 @@ window_copy_cmd_rectangle_toggle(struct window_copy_cmd_state *cs) struct window_copy_mode_data *data = wme->data; data->lineflag = LINE_SEL_NONE; - window_copy_rectangle_toggle(wme); + window_copy_rectangle_set(wme, !data->rectflag); return (WINDOW_COPY_CMD_NOTHING); } @@ -2251,6 +2275,10 @@ static const struct { window_copy_cmd_previous_space }, { "previous-word", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, window_copy_cmd_previous_word }, + { "rectangle-on", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, + window_copy_cmd_rectangle_on }, + { "rectangle-off", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, + window_copy_cmd_rectangle_off }, { "rectangle-toggle", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, window_copy_cmd_rectangle_toggle }, { "refresh-from-pane", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, @@ -4726,12 +4754,12 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny) } static void -window_copy_rectangle_toggle(struct window_mode_entry *wme) +window_copy_rectangle_set(struct window_mode_entry *wme, int rectflag) { struct window_copy_mode_data *data = wme->data; u_int px, py; - data->rectflag = !data->rectflag; + data->rectflag = rectflag; py = screen_hsize(data->backing) + data->cy - data->oy; px = window_copy_find_length(wme, py); -- cgit From e3005e5ec4385d284abdeb3cecafc69c14655649 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 8 Feb 2021 14:46:53 +0000 Subject: Add "pipe" variants of the "copy-pipe" commands which do not copy, from Christian Zangl. --- window-copy.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 6 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 89b2a9af..c6b25413 100644 --- a/window-copy.c +++ b/window-copy.c @@ -92,6 +92,8 @@ static void window_copy_synchronize_cursor(struct window_mode_entry *, int); static void *window_copy_get_selection(struct window_mode_entry *, size_t *); static void window_copy_copy_buffer(struct window_mode_entry *, const char *, void *, size_t); +static void window_copy_pipe(struct window_mode_entry *, + struct session *, const char *); static void window_copy_copy_pipe(struct window_mode_entry *, struct session *, const char *, const char *); static void window_copy_copy_selection(struct window_mode_entry *, @@ -1874,6 +1876,44 @@ window_copy_cmd_copy_pipe_and_cancel(struct window_copy_cmd_state *cs) return (WINDOW_COPY_CMD_CANCEL); } +static enum window_copy_cmd_action +window_copy_cmd_pipe_no_clear(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; + struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + char *command = NULL; + + if (s != NULL && cs->args->argc > 1 && *cs->args->argv[1] != '\0') + command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + window_copy_pipe(wme, s, command); + free(command); + + return (WINDOW_COPY_CMD_NOTHING); +} + +static enum window_copy_cmd_action +window_copy_cmd_pipe(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + + window_copy_cmd_pipe_no_clear(cs); + window_copy_clear_selection(wme); + return (WINDOW_COPY_CMD_REDRAW); +} + +static enum window_copy_cmd_action +window_copy_cmd_pipe_and_cancel(struct window_copy_cmd_state *cs) +{ + struct window_mode_entry *wme = cs->wme; + + window_copy_cmd_pipe_no_clear(cs); + window_copy_clear_selection(wme); + return (WINDOW_COPY_CMD_CANCEL); +} + static enum window_copy_cmd_action window_copy_cmd_goto_line(struct window_copy_cmd_state *cs) { @@ -2267,6 +2307,12 @@ static const struct { window_copy_cmd_page_down_and_cancel }, { "page-up", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, window_copy_cmd_page_up }, + { "pipe-no-clear", 0, 1, WINDOW_COPY_CMD_CLEAR_NEVER, + window_copy_cmd_pipe_no_clear }, + { "pipe", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, + window_copy_cmd_pipe }, + { "pipe-and-cancel", 0, 1, WINDOW_COPY_CMD_CLEAR_ALWAYS, + window_copy_cmd_pipe_and_cancel }, { "previous-matching-bracket", 0, 0, WINDOW_COPY_CMD_CLEAR_ALWAYS, window_copy_cmd_previous_matching_bracket }, { "previous-paragraph", 0, 0, WINDOW_COPY_CMD_CLEAR_EMACS_ONLY, @@ -3840,22 +3886,41 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix, paste_add(prefix, buf, len); } -static void -window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s, - const char *prefix, const char *cmd) +static void * +window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, + const char *cmd, size_t *len) { void *buf; - size_t len; struct job *job; - buf = window_copy_get_selection(wme, &len); + buf = window_copy_get_selection(wme, len); if (cmd == NULL || *cmd == '\0') cmd = options_get_string(global_options, "copy-command"); if (cmd != NULL && *cmd != '\0') { job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT, -1, -1); - bufferevent_write(job_get_event(job), buf, len); + bufferevent_write(job_get_event(job), buf, *len); } + return (buf); +} + +static void +window_copy_pipe(struct window_mode_entry *wme, struct session *s, + const char *cmd) +{ + size_t len; + + window_copy_pipe_run(wme, s, cmd, &len); +} + +static void +window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s, + const char *prefix, const char *cmd) +{ + void *buf; + size_t len; + + buf = window_copy_pipe_run(wme, s, cmd, &len); if (buf != NULL) window_copy_copy_buffer(wme, prefix, buf, len); } -- cgit From 8986c8dfcd0083e5c767b8a247c119a25e1f8093 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 22 Feb 2021 06:53:04 +0000 Subject: Move jump commands to grid reader, make them UTF-8 aware, and tidy up, from Anindya Mukherjee. --- window-copy.c | 344 +++++++++++++++++++++++----------------------------------- 1 file changed, 133 insertions(+), 211 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index c6b25413..af8d2937 100644 --- a/window-copy.c +++ b/window-copy.c @@ -135,6 +135,10 @@ static void window_copy_move_mouse(struct mouse_event *); static void window_copy_drag_update(struct client *, struct mouse_event *); static void window_copy_drag_release(struct client *, struct mouse_event *); static void window_copy_jump_to_mark(struct window_mode_entry *); +static void window_copy_acquire_cursor_up(struct window_mode_entry *, + u_int, u_int, u_int, u_int, u_int); +static void window_copy_acquire_cursor_down(struct window_mode_entry *, + u_int, u_int, u_int, u_int, u_int, u_int, int); const struct window_mode window_copy_mode = { .name = "copy-mode", @@ -284,8 +288,8 @@ struct window_copy_mode_data { #define WINDOW_COPY_SEARCH_TIMEOUT 10000 #define WINDOW_COPY_SEARCH_ALL_TIMEOUT 200 - int jumptype; - char jumpchar; + int jumptype; + struct utf8_data *jumpchar; struct event dragtimer; #define WINDOW_COPY_DRAG_REPEAT_TIME 50000 @@ -401,7 +405,7 @@ window_copy_common_init(struct window_mode_entry *wme) data->searchall = 1; data->jumptype = WINDOW_COPY_OFF; - data->jumpchar = '\0'; + data->jumpchar = NULL; screen_init(&data->screen, screen_size_x(base), screen_size_y(base), 0); data->modekeys = options_get_number(wp->window->options, "mode-keys"); @@ -482,6 +486,7 @@ window_copy_free(struct window_mode_entry *wme) free(data->searchmark); free(data->searchstr); + free(data->jumpchar); screen_free(data->backing); free(data->backing); @@ -1935,7 +1940,8 @@ window_copy_cmd_jump_backward(struct window_copy_cmd_state *cs) if (*argument != '\0') { data->jumptype = WINDOW_COPY_JUMPBACKWARD; - data->jumpchar = *argument; + free(data->jumpchar); + data->jumpchar = utf8_fromcstr(argument); for (; np != 0; np--) window_copy_cursor_jump_back(wme); } @@ -1952,7 +1958,8 @@ window_copy_cmd_jump_forward(struct window_copy_cmd_state *cs) if (*argument != '\0') { data->jumptype = WINDOW_COPY_JUMPFORWARD; - data->jumpchar = *argument; + free(data->jumpchar); + data->jumpchar = utf8_fromcstr(argument); for (; np != 0; np--) window_copy_cursor_jump(wme); } @@ -1969,7 +1976,8 @@ window_copy_cmd_jump_to_backward(struct window_copy_cmd_state *cs) if (*argument != '\0') { data->jumptype = WINDOW_COPY_JUMPTOBACKWARD; - data->jumpchar = *argument; + free(data->jumpchar); + data->jumpchar = utf8_fromcstr(argument); for (; np != 0; np--) window_copy_cursor_jump_to_back(wme); } @@ -1986,7 +1994,8 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs) if (*argument != '\0') { data->jumptype = WINDOW_COPY_JUMPTOFORWARD; - data->jumpchar = *argument; + free(data->jumpchar); + data->jumpchar = utf8_fromcstr(argument); for (; np != 0; np--) window_copy_cursor_jump_to(wme); } @@ -4074,7 +4083,7 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, oldy, yy, ny, nd, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); @@ -4084,25 +4093,7 @@ window_copy_cursor_start_of_line(struct window_mode_entry *wme) grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_start_of_line(&gr, 1); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll up if we went off the visible screen. */ - yy = hsize - data->oy; - if (py < yy) { - ny = yy - py; - cy = 0; - nd = 1; - } else { - ny = 0; - cy = py - yy; - nd = oldy - cy + 1; - } - while (ny > 0) { - window_copy_cursor_up(wme, 1); - ny--; - } - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, nd); + window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py); } static void @@ -4134,7 +4125,7 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, oldy, yy, ny, nd, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); @@ -4147,28 +4138,8 @@ window_copy_cursor_end_of_line(struct window_mode_entry *wme) else grid_reader_cursor_end_of_line(&gr, 1, 0); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll down if we went off the visible screen. */ - cy = py - hsize + data->oy; - yy = screen_size_y(back_s) - 1; - if (cy > yy) { - ny = cy - yy; - oldy = yy; - nd = 1; - } else { - ny = 0; - nd = cy - oldy + 1; - } - while (ny > 0) { - window_copy_cursor_down(wme, 1); - ny--; - } - if (cy > yy) - window_copy_update_cursor(wme, px, yy); - else - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, oldy, nd); + window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s), + data->oy, oldy, px, py, 0); } static void @@ -4228,32 +4199,17 @@ window_copy_cursor_left(struct window_mode_entry *wme) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_left(&gr); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll up if we went off the visible screen. */ - yy = hsize - data->oy; - if (py < yy) { - ny = yy - py; - cy = 0; - } else { - ny = 0; - cy = py - yy; - } - while (ny > 0) { - window_copy_cursor_up(wme, 1); - ny--; - } - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py); } static void @@ -4262,33 +4218,18 @@ window_copy_cursor_right(struct window_mode_entry *wme, int all) struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, yy, ny, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); py = hsize + data->cy - data->oy; + oldy = data->cy; grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_right(&gr, 1, all); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll down if we went off the visible screen. */ - cy = py - hsize + data->oy; - yy = screen_size_y(back_s) - 1; - if (cy > yy) - ny = cy - yy; - else - ny = 0; - while (ny > 0) { - window_copy_cursor_down(wme, 1); - ny--; - } - if (cy > yy) - window_copy_update_cursor(wme, px, yy); - else - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); + window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s), + data->oy, oldy, px, py, 0); } static void @@ -4422,23 +4363,19 @@ window_copy_cursor_jump(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid_cell gc; - u_int px, py, xx; + struct grid_reader gr; + u_int px, py, oldy, hsize; px = data->cx + 1; - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + oldy = data->cy; - while (px < xx) { - grid_get_cell(back_s->grid, px, py, &gc); - if (!(gc.flags & GRID_FLAG_PADDING) && - gc.data.size == 1 && *gc.data.data == data->jumpchar) { - window_copy_update_cursor(wme, px, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); - return; - } - px++; + grid_reader_start(&gr, back_s->grid, px, py); + if (grid_reader_cursor_jump(&gr, data->jumpchar)) { + grid_reader_get_cursor(&gr, &px, &py); + window_copy_acquire_cursor_down(wme, hsize, + screen_size_y(back_s), data->oy, oldy, px, py, 0); } } @@ -4447,27 +4384,22 @@ window_copy_cursor_jump_back(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid_cell gc; - u_int px, py; + struct grid_reader gr; + u_int px, py, oldy, hsize; px = data->cx; - py = screen_hsize(back_s) + data->cy - data->oy; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + oldy = data->cy; if (px > 0) px--; - for (;;) { - grid_get_cell(back_s->grid, px, py, &gc); - if (!(gc.flags & GRID_FLAG_PADDING) && - gc.data.size == 1 && *gc.data.data == data->jumpchar) { - window_copy_update_cursor(wme, px, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); - return; - } - if (px == 0) - break; - px--; + grid_reader_start(&gr, back_s->grid, px, py); + if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) { + grid_reader_get_cursor(&gr, &px, &py); + window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, + py); } } @@ -4476,23 +4408,20 @@ window_copy_cursor_jump_to(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid_cell gc; - u_int px, py, xx; + struct grid_reader gr; + u_int px, py, oldy, hsize; px = data->cx + 2; - py = screen_hsize(back_s) + data->cy - data->oy; - xx = window_copy_find_length(wme, py); + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + oldy = data->cy; - while (px < xx) { - grid_get_cell(back_s->grid, px, py, &gc); - if (!(gc.flags & GRID_FLAG_PADDING) && - gc.data.size == 1 && *gc.data.data == data->jumpchar) { - window_copy_update_cursor(wme, px - 1, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); - return; - } - px++; + grid_reader_start(&gr, back_s->grid, px, py); + if (grid_reader_cursor_jump(&gr, data->jumpchar)) { + grid_reader_cursor_left(&gr); + grid_reader_get_cursor(&gr, &px, &py); + window_copy_acquire_cursor_down(wme, hsize, + screen_size_y(back_s), data->oy, oldy, px, py, 0); } } @@ -4501,11 +4430,13 @@ window_copy_cursor_jump_to_back(struct window_mode_entry *wme) { struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; - struct grid_cell gc; - u_int px, py; + struct grid_reader gr; + u_int px, py, oldy, hsize; px = data->cx; - py = screen_hsize(back_s) + data->cy - data->oy; + hsize = screen_hsize(back_s); + py = hsize + data->cy - data->oy; + oldy = data->cy; if (px > 0) px--; @@ -4513,18 +4444,12 @@ window_copy_cursor_jump_to_back(struct window_mode_entry *wme) if (px > 0) px--; - for (;;) { - grid_get_cell(back_s->grid, px, py, &gc); - if (!(gc.flags & GRID_FLAG_PADDING) && - gc.data.size == 1 && *gc.data.data == data->jumpchar) { - window_copy_update_cursor(wme, px + 1, data->cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, 1); - return; - } - if (px == 0) - break; - px--; + grid_reader_start(&gr, back_s->grid, px, py); + if (grid_reader_cursor_jump_back(&gr, data->jumpchar)) { + grid_reader_cursor_right(&gr, 1, 0); + grid_reader_get_cursor(&gr, &px, &py); + window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, + py); } } @@ -4535,7 +4460,7 @@ window_copy_cursor_next_word(struct window_mode_entry *wme, struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, oldy, yy, ny, nd, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); @@ -4545,28 +4470,8 @@ window_copy_cursor_next_word(struct window_mode_entry *wme, grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_next_word(&gr, separators); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll down if we went off the visible screen. */ - cy = py - hsize + data->oy; - yy = screen_size_y(back_s) - 1; - if (cy > yy) { - ny = cy - yy; - oldy = yy; - nd = 1; - } else { - ny = 0; - nd = cy - oldy + 1; - } - while (ny > 0) { - window_copy_cursor_down(wme, 1); - ny--; - } - if (cy > yy) - window_copy_update_cursor(wme, px, yy); - else - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, oldy, nd); + window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s), + data->oy, oldy, px, py, 0); } static void @@ -4627,7 +4532,7 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, struct options *oo = wp->window->options; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, oldy, yy, ny, nd, hsize; + u_int px, py, oldy, hsize; int keys; px = data->cx; @@ -4643,28 +4548,8 @@ window_copy_cursor_next_word_end(struct window_mode_entry *wme, if (keys == MODEKEY_VI) grid_reader_cursor_left(&gr); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll down if we went off the visible screen. */ - cy = py - hsize + data->oy; - yy = screen_size_y(back_s) - 1; - if (cy > yy) { - ny = cy - yy; - oldy = yy; - nd = 1; - } else { - ny = 0; - nd = cy - oldy + 1; - } - while (ny > 0) { - window_copy_cursor_down(wme, 1); - ny--; - } - if (cy > yy) - window_copy_update_cursor(wme, px, yy); - else - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, no_reset)) - window_copy_redraw_lines(wme, oldy, nd); + window_copy_acquire_cursor_down(wme, hsize, screen_size_y(back_s), + data->oy, oldy, px, py, no_reset); } /* Compute the previous place where a word begins. */ @@ -4721,7 +4606,7 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, struct window_copy_mode_data *data = wme->data; struct screen *back_s = data->backing; struct grid_reader gr; - u_int px, py, cy, oldy, yy, ny, nd, hsize; + u_int px, py, oldy, hsize; px = data->cx; hsize = screen_hsize(back_s); @@ -4731,25 +4616,7 @@ window_copy_cursor_previous_word(struct window_mode_entry *wme, grid_reader_start(&gr, back_s->grid, px, py); grid_reader_cursor_previous_word(&gr, separators, already); grid_reader_get_cursor(&gr, &px, &py); - - /* Scroll up if we went off the visible screen. */ - yy = hsize - data->oy; - if (py < yy) { - ny = yy - py; - cy = 0; - nd = 1; - } else { - ny = 0; - cy = py - yy; - nd = oldy - cy + 1; - } - while (ny > 0) { - window_copy_cursor_up(wme, 1); - ny--; - } - window_copy_update_cursor(wme, px, cy); - if (window_copy_update_selection(wme, 1, 0)) - window_copy_redraw_lines(wme, data->cy, nd); + window_copy_acquire_cursor_up(wme, hsize, data->oy, oldy, px, py); } static void @@ -5000,3 +4867,58 @@ window_copy_jump_to_mark(struct window_mode_entry *wme) window_copy_update_selection(wme, 0, 0); window_copy_redraw_screen(wme); } + +/* Scroll up if the cursor went off the visible screen. */ +static void +window_copy_acquire_cursor_up(struct window_mode_entry *wme, u_int hsize, + u_int oy, u_int oldy, u_int px, u_int py) +{ + u_int cy, yy, ny, nd; + + yy = hsize - oy; + if (py < yy) { + ny = yy - py; + cy = 0; + nd = 1; + } else { + ny = 0; + cy = py - yy; + nd = oldy - cy + 1; + } + while (ny > 0) { + window_copy_cursor_up(wme, 1); + ny--; + } + window_copy_update_cursor(wme, px, cy); + if (window_copy_update_selection(wme, 1, 0)) + window_copy_redraw_lines(wme, cy, nd); +} + +/* Scroll down if the cursor went off the visible screen. */ +static void +window_copy_acquire_cursor_down(struct window_mode_entry *wme, u_int hsize, + u_int sy, u_int oy, u_int oldy, u_int px, u_int py, int no_reset) +{ + u_int cy, yy, ny, nd; + + cy = py - hsize + oy; + yy = sy - 1; + if (cy > yy) { + ny = cy - yy; + oldy = yy; + nd = 1; + } else { + ny = 0; + nd = cy - oldy + 1; + } + while (ny > 0) { + window_copy_cursor_down(wme, 1); + ny--; + } + if (cy > yy) + window_copy_update_cursor(wme, px, yy); + else + window_copy_update_cursor(wme, px, cy); + if (window_copy_update_selection(wme, 1, no_reset)) + window_copy_redraw_lines(wme, oldy, nd); +} -- cgit From e858270006a9041b9016ed9e6cc12d622ac8fe31 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 22 Feb 2021 07:09:06 +0000 Subject: There are many format variables now so allocating all the default ones each time a tree is created is too expensive. Instead, convert them all into callbacks and put them in a static table so they only allocate on demand. The tree remains for the moment for extra (non-default) variables added by for example copy mode or popups. Also reduce expensive calls to localtime_r/strftime. GitHub issue 2253. --- window-copy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index af8d2937..2f4b06e8 100644 --- a/window-copy.c +++ b/window-copy.c @@ -710,7 +710,7 @@ window_copy_get_line(struct window_pane *wp, u_int y) return (format_grid_line(gd, gd->hsize + y)); } -static char * +static void * window_copy_cursor_word_cb(struct format_tree *ft) { struct window_pane *wp = format_get_pane(ft); @@ -720,7 +720,7 @@ window_copy_cursor_word_cb(struct format_tree *ft) return (window_copy_get_word(wp, data->cx, data->cy)); } -static char * +static void * window_copy_cursor_line_cb(struct format_tree *ft) { struct window_pane *wp = format_get_pane(ft); @@ -730,7 +730,7 @@ window_copy_cursor_line_cb(struct format_tree *ft) return (window_copy_get_line(wp, data->cy)); } -static char * +static void * window_copy_search_match_cb(struct format_tree *ft) { struct window_pane *wp = format_get_pane(ft); -- cgit From 5f425ee31810c964ae5cf1256d0d7fe5dde7536c Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 22 Feb 2021 08:31:19 +0000 Subject: Fix regex searching with wrapped lines, from Anindya Mukherjee; GitHub issue 2570. --- window-copy.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 2f4b06e8..531431c8 100644 --- a/window-copy.c +++ b/window-copy.c @@ -73,6 +73,8 @@ static int window_copy_search_marks(struct window_mode_entry *, static void window_copy_clear_marks(struct window_mode_entry *); static void window_copy_move_left(struct screen *, u_int *, u_int *, int); static int window_copy_is_lowercase(const char *); +static void window_copy_search_back_overlap(struct grid *, regex_t *, + u_int *, u_int *, u_int *, u_int); static int window_copy_search_jump(struct window_mode_entry *, struct grid *, struct grid *, u_int, u_int, u_int, int, int, int, int, u_int *); @@ -2912,6 +2914,48 @@ window_copy_is_lowercase(const char *ptr) return (1); } +/* + * Handle backward wrapped regex searches with overlapping matches. In this case + * find the longest overlapping match from previous wrapped lines. + */ +static void +window_copy_search_back_overlap(struct grid *gd, regex_t *preg, u_int *ppx, + u_int *psx, u_int *ppy, u_int endline) +{ + u_int endx, endy, oldendx, oldendy, px, py, sx; + int found = 1; + + oldendx = *ppx + *psx; + oldendy = *ppy - 1; + while (oldendx > gd->sx - 1) { + oldendx -= gd->sx; + oldendy++; + } + endx = oldendx; + endy = oldendy; + px = *ppx; + py = *ppy; + while (found && px == 0 && py - 1 > endline && + grid_get_line(gd, py - 2)->flags & GRID_LINE_WRAPPED && + endx == oldendx && endy == oldendy) { + py--; + found = window_copy_search_rl_regex(gd, &px, &sx, py - 1, 0, + gd->sx, preg); + if (found) { + endx = px + sx; + endy = py - 1; + while (endx > gd->sx - 1) { + endx -= gd->sx; + endy++; + } + if (endx == oldendx && endy == oldendy) { + *ppx = px; + *ppy = py; + } + } + } +} + /* * Search for text stored in sgd starting from position fx,fy up to endline. If * found, jump to it. If cis then ignore case. The direction is 0 for searching @@ -2964,6 +3008,10 @@ window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd, if (regex) { found = window_copy_search_rl_regex(gd, &px, &sx, i - 1, 0, fx + 1, ®); + if (found) { + window_copy_search_back_overlap(gd, + ®, &px, &sx, &i, endline); + } } else { found = window_copy_search_rl(gd, sgd, &px, i - 1, 0, fx + 1, cis); @@ -3048,6 +3096,12 @@ window_copy_search(struct window_mode_entry *wme, int direction, int regex, if (found) { window_copy_search_marks(wme, &ss, regex, visible_only); if (foundlen != 0) { + /* Adjust for wrapped lines eating one right. */ + i = data->cx + foundlen; + while (i > gd->sx - 1) { + i -= gd->sx; + window_copy_cursor_right(wme, 1); + } for (i = 0; i < foundlen; i++) window_copy_cursor_right(wme, 1); } @@ -3164,8 +3218,11 @@ again: if (window_copy_search_mark_at(data, px, py, &b) == 0) { if (b + width > gd->sx * gd->sy) width = (gd->sx * gd->sy) - b; - for (i = b; i < b + width; i++) + for (i = b; i < b + width; i++) { + if (data->searchmark[i] != 0) + continue; data->searchmark[i] = data->searchgen; + } if (data->searchgen == UCHAR_MAX) data->searchgen = 1; else -- cgit From c44750792a9683c5cd6f9df5a69e7417b88772d2 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Mar 2021 10:56:45 +0000 Subject: Drop support for popups where the content is provided directly to tmux (which does not have many practical uses) and only support running a program in the popup. display-popup is now simpler and can accept multiple arguments to avoid escaping problems (like the other commands). --- window-copy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'window-copy.c') diff --git a/window-copy.c b/window-copy.c index 531431c8..4558ed48 100644 --- a/window-copy.c +++ b/window-copy.c @@ -3963,8 +3963,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, if (cmd == NULL || *cmd == '\0') cmd = options_get_string(global_options, "copy-command"); if (cmd != NULL && *cmd != '\0') { - job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT, - -1, -1); + job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL, + JOB_NOWAIT, -1, -1); bufferevent_write(job_get_event(job), buf, *len); } return (buf); -- cgit