From: nicm Date: Mon, 22 Feb 2021 08:31:19 +0000 (+0000) Subject: Fix regex searching with wrapped lines, from Anindya Mukherjee; GitHub X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=d51414ae146073ca345dc2fad70797db78fc4ab0;p=openbsd Fix regex searching with wrapped lines, from Anindya Mukherjee; GitHub issue 2570. --- diff --git a/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c index fbe66f96fb0..2576b9993ac 100644 --- a/usr.bin/tmux/window-copy.c +++ b/usr.bin/tmux/window-copy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-copy.c,v 1.316 2021/02/22 07:09:06 nicm Exp $ */ +/* $OpenBSD: window-copy.c,v 1.317 2021/02/22 08:31:19 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -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