=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/window-copy.c,v retrieving revision 1.320 retrieving revision 1.321 diff -c -r1.320 -r1.321 *** src/usr.bin/tmux/window-copy.c 2021/03/09 13:07:50 1.320 --- src/usr.bin/tmux/window-copy.c 2021/04/01 06:46:12 1.321 *************** *** 1,4 **** ! /* $OpenBSD: window-copy.c,v 1.320 2021/03/09 13:07:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: window-copy.c,v 1.321 2021/04/01 06:46:12 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 64,69 **** --- 64,71 ---- static int window_copy_last_regex(struct grid *, u_int, u_int, u_int, u_int, u_int *, u_int *, const char *, const regex_t *, int); + static int window_copy_search_mark_at(struct window_copy_mode_data *, + u_int, u_int, u_int *); static char *window_copy_stringify(struct grid *, u_int, u_int, u_int, char *, u_int *); static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *, *************** *** 71,86 **** static int window_copy_search_marks(struct window_mode_entry *, struct screen *, int, int); 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 *); ! static int window_copy_search(struct window_mode_entry *, int, int, int); ! static int window_copy_search_up(struct window_mode_entry *, int, int); ! static int window_copy_search_down(struct window_mode_entry *, int, int); static void window_copy_goto_line(struct window_mode_entry *, const char *); static void window_copy_update_cursor(struct window_mode_entry *, u_int, u_int); --- 73,87 ---- static int window_copy_search_marks(struct window_mode_entry *, struct screen *, int, int); static void window_copy_clear_marks(struct window_mode_entry *); 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); ! static int window_copy_search(struct window_mode_entry *, int, int); ! static int window_copy_search_up(struct window_mode_entry *, int); ! static int window_copy_search_down(struct window_mode_entry *, int); static void window_copy_goto_line(struct window_mode_entry *, const char *); static void window_copy_update_cursor(struct window_mode_entry *, u_int, u_int); *************** *** 275,280 **** --- 276,282 ---- int showmark; int searchtype; + int searchdirection; int searchregex; char *searchstr; u_char *searchmark; *************** *** 1718,1727 **** if (data->searchtype == WINDOW_COPY_SEARCHUP) { for (; np != 0; np--) ! window_copy_search_up(wme, data->searchregex, 1); } else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { for (; np != 0; np--) ! window_copy_search_down(wme, data->searchregex, 1); } return (WINDOW_COPY_CMD_NOTHING); } --- 1720,1729 ---- if (data->searchtype == WINDOW_COPY_SEARCHUP) { for (; np != 0; np--) ! window_copy_search_up(wme, data->searchregex); } else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { for (; np != 0; np--) ! window_copy_search_down(wme, data->searchregex); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 1735,1744 **** if (data->searchtype == WINDOW_COPY_SEARCHUP) { for (; np != 0; np--) ! window_copy_search_down(wme, data->searchregex, 1); } else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { for (; np != 0; np--) ! window_copy_search_up(wme, data->searchregex, 1); } return (WINDOW_COPY_CMD_NOTHING); } --- 1737,1746 ---- if (data->searchtype == WINDOW_COPY_SEARCHUP) { for (; np != 0; np--) ! window_copy_search_down(wme, data->searchregex); } else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { for (; np != 0; np--) ! window_copy_search_up(wme, data->searchregex); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 2042,2048 **** data->searchregex = 1; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_up(wme, 1, 0); } return (WINDOW_COPY_CMD_NOTHING); } --- 2044,2050 ---- data->searchregex = 1; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_up(wme, 1); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 2062,2068 **** data->searchregex = 0; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_up(wme, 0, 0); } return (WINDOW_COPY_CMD_NOTHING); } --- 2064,2070 ---- data->searchregex = 0; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_up(wme, 0); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 2082,2088 **** data->searchregex = 1; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_down(wme, 1, 0); } return (WINDOW_COPY_CMD_NOTHING); } --- 2084,2090 ---- data->searchregex = 1; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_down(wme, 1); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 2102,2108 **** data->searchregex = 0; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_down(wme, 0, 0); } return (WINDOW_COPY_CMD_NOTHING); } --- 2104,2110 ---- data->searchregex = 0; data->timeout = 0; for (; np != 0; np--) ! window_copy_search_down(wme, 0); } return (WINDOW_COPY_CMD_NOTHING); } *************** *** 2143,2149 **** data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_up(wme, 0, 1)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } --- 2145,2151 ---- data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } *************** *** 2153,2159 **** data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_down(wme, 0, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } --- 2155,2161 ---- data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } *************** *** 2198,2204 **** data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_down(wme, 0, 1)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } --- 2200,2206 ---- data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_down(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } *************** *** 2208,2214 **** data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_up(wme, 0, 1)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } --- 2210,2216 ---- data->searchregex = 0; free(data->searchstr); data->searchstr = xstrdup(argument); ! if (!window_copy_search_up(wme, 0)) { window_copy_clear_marks(wme); return (WINDOW_COPY_CMD_REDRAW); } *************** *** 2917,2922 **** --- 2919,2941 ---- *fx = *fx - 1; } + static void + window_copy_move_right(struct screen *s, u_int *fx, u_int *fy, int wrapflag) + { + if (*fx == screen_size_x(s) - 1) { /* right */ + if (*fy == screen_hsize(s) + screen_size_y(s) - 1) { /* bottom */ + if (wrapflag) { + *fx = 0; + *fy = 0; + } + return; + } + *fx = 0; + *fy = *fy + 1; + } else + *fx = *fx + 1; + } + static int window_copy_is_lowercase(const char *ptr) { *************** *** 2979,2985 **** static int window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd, struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap, ! int direction, int regex, u_int *foundlen) { u_int i, px, sx, ssize = 1; int found = 0, cflags = REG_EXTENDED; --- 2998,3004 ---- static int window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd, struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap, ! int direction, int regex) { u_int i, px, sx, ssize = 1; int found = 0, cflags = REG_EXTENDED; *************** *** 3004,3023 **** if (regex) { found = window_copy_search_lr_regex(gd, &px, &sx, i, fx, gd->sx, ®); - if (found) - *foundlen = sx; } else { found = window_copy_search_lr(gd, sgd, &px, i, fx, gd->sx, cis); - if (found) - *foundlen = sgd->sx; } if (found) break; fx = 0; } } else { - *foundlen = 0; for (i = fy + 1; endline < i; i--) { if (regex) { found = window_copy_search_rl_regex(gd, --- 3023,3037 ---- *************** *** 3048,3065 **** return (window_copy_search_jump(wme, gd, sgd, direction ? 0 : gd->sx - 1, direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0, ! direction, regex, foundlen)); } return (0); } /* * Search in for text searchstr. If direction is 0 then search up, otherwise * down. */ static int ! window_copy_search(struct window_mode_entry *wme, int direction, int regex, ! int again) { struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; --- 3062,3101 ---- return (window_copy_search_jump(wme, gd, sgd, direction ? 0 : gd->sx - 1, direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0, ! direction, regex)); } return (0); } + static void + window_copy_move_after_search_mark(struct window_copy_mode_data *data, + u_int *fx, u_int *fy, int wrapflag) + { + struct screen *s = data->backing; + u_int at, start; + + if (window_copy_search_mark_at(data, *fx, *fy, &start) == 0 && + data->searchmark[start] != 0) { + while (window_copy_search_mark_at(data, *fx, *fy, &at) == 0) { + if (data->searchmark[at] != data->searchmark[start]) + break; + /* Stop if not wrapping and at the end of the grid. */ + if (!wrapflag && + *fx == screen_size_x(s) - 1 && + *fy == screen_hsize(s) + screen_size_y(s) - 1) + break; + + window_copy_move_right(s, fx, fy, wrapflag); + } + } + } + /* * Search in for text searchstr. If direction is 0 then search up, otherwise * down. */ static int ! window_copy_search(struct window_mode_entry *wme, int direction, int regex) { struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; *************** *** 3067,3078 **** struct screen_write_ctx ctx; struct grid *gd = s->grid; const char *str = data->searchstr; ! u_int fx, fy, endline, i, foundlen; ! int wrapflag, cis, found, visible_only; if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0') regex = 0; if (data->timeout) return (0); --- 3103,3117 ---- struct screen_write_ctx ctx; struct grid *gd = s->grid; const char *str = data->searchstr; ! u_int at, endline, fx, fy, start; ! int cis, found, keys, visible_only; ! int wrapflag; if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0') regex = 0; + data->searchdirection = direction; + if (data->timeout) return (0); *************** *** 3097,3124 **** wrapflag = options_get_number(wp->window->options, "wrap-search"); cis = window_copy_is_lowercase(str); ! if (direction) endline = gd->hsize + gd->sy - 1; else { ! if (again) ! window_copy_move_left(s, &fx, &fy, wrapflag); endline = 0; } found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis, ! wrapflag, direction, regex, &foundlen); 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); } } window_copy_redraw_screen(wme); --- 3136,3230 ---- wrapflag = options_get_number(wp->window->options, "wrap-search"); cis = window_copy_is_lowercase(str); ! keys = options_get_number(wp->window->options, "mode-keys"); ! ! if (direction) { ! /* ! * Behave according to mode-keys. If it is emacs, search forward ! * leaves the cursor after the match. If it is vi, the cursor ! * remains at the beginning of the match, regardless of ! * direction, which means that we need to start the next search ! * after the term the cursor is currently on when searching ! * forward. ! */ ! if (keys == MODEKEY_VI) { ! if (data->searchmark != NULL) ! window_copy_move_after_search_mark(data, &fx, ! &fy, wrapflag); ! else { ! /* ! * When there are no search marks, start the ! * search after the current cursor position. ! */ ! window_copy_move_right(s, &fx, &fy, wrapflag); ! } ! } endline = gd->hsize + gd->sy - 1; + } else { ! window_copy_move_left(s, &fx, &fy, wrapflag); endline = 0; } found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis, ! wrapflag, direction, regex); if (found) { window_copy_search_marks(wme, &ss, regex, visible_only); ! fx = data->cx; ! fy = screen_hsize(data->backing) - data->oy + data->cy; ! ! /* ! * When searching forward, if the cursor is not at the beginning ! * of the mark, search again. ! */ ! if (direction && ! window_copy_search_mark_at(data, fx, fy, &at) == 0 && ! at > 0 && ! data->searchmark[at] == data->searchmark[at - 1]) { ! window_copy_move_after_search_mark(data, &fx, &fy, ! wrapflag); ! window_copy_search_jump(wme, gd, ss.grid, fx, ! fy, endline, cis, wrapflag, direction, ! regex); ! fx = data->cx; ! fy = screen_hsize(data->backing) - data->oy + data->cy; ! } ! ! if (direction) { ! /* ! * When in Emacs mode, position the cursor just after ! * the mark. ! */ ! if (keys == MODEKEY_EMACS) { ! window_copy_move_after_search_mark(data, &fx, ! &fy, wrapflag); ! data->cx = fx; ! data->cy = fy - screen_hsize(data->backing) + ! data-> oy; } } + else { + /* + * When searching backward, position the cursor at the + * beginning of the mark. + */ + if (window_copy_search_mark_at(data, fx, fy, + &start) == 0) { + while (window_copy_search_mark_at(data, fx, fy, + &at) == 0 && + data->searchmark[at] == + data->searchmark[start]) { + data->cx = fx; + data->cy = fy - + screen_hsize(data->backing) + + data-> oy; + if (at == 0) + break; + + window_copy_move_left(s, &fx, &fy, 0); + } + } + } } window_copy_redraw_screen(wme); *************** *** 3302,3316 **** } static int ! window_copy_search_up(struct window_mode_entry *wme, int regex, int again) { ! return (window_copy_search(wme, 0, regex, again)); } static int ! window_copy_search_down(struct window_mode_entry *wme, int regex, int again) { ! return (window_copy_search(wme, 1, regex, again)); } static void --- 3408,3422 ---- } static int ! window_copy_search_up(struct window_mode_entry *wme, int regex) { ! return (window_copy_search(wme, 0, regex)); } static int ! window_copy_search_down(struct window_mode_entry *wme, int regex) { ! return (window_copy_search(wme, 1, regex)); } static void *************** *** 3396,3404 **** --- 3502,3512 ---- struct grid_cell *gc, const struct grid_cell *mgc, const struct grid_cell *cgc, const struct grid_cell *mkgc) { + struct window_pane *wp = wme->wp; struct window_copy_mode_data *data = wme->data; u_int mark, start, end, cy, cursor, current; int inv = 0, found = 0; + int keys; if (data->showmark && fy == data->my) { gc->attr = mkgc->attr; *************** *** 3425,3437 **** cy = screen_hsize(data->backing) - data->oy + data->cy; if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) { ! if (data->searchmark[cursor] == mark) ! found = 1; ! else if (cursor != 0) { ! cursor--; ! if (data->searchmark[cursor] == mark) found = 1; ! } if (found) { window_copy_match_start_end(data, cursor, &start, &end); if (current >= start && current <= end) { --- 3533,3548 ---- cy = screen_hsize(data->backing) - data->oy + data->cy; if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) { ! keys = options_get_number(wp->window->options, "mode-keys"); ! if (cursor != 0 && ! keys == MODEKEY_EMACS && ! data->searchdirection) { ! if (data->searchmark[cursor - 1] == mark) { ! cursor--; found = 1; ! } ! } else if (data->searchmark[cursor] == mark) ! found = 1; if (found) { window_copy_match_start_end(data, cursor, &start, &end); if (current >= start && current <= end) {