version 1.320, 2021/03/09 13:07:50 |
version 1.321, 2021/04/01 06:46:12 |
|
|
static int window_copy_last_regex(struct grid *, u_int, u_int, u_int, |
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 *, |
u_int, u_int *, u_int *, const char *, const regex_t *, |
int); |
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, |
static char *window_copy_stringify(struct grid *, u_int, u_int, u_int, |
char *, u_int *); |
char *, u_int *); |
static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *, |
static void window_copy_cstrtocellpos(struct grid *, u_int, u_int *, |
|
|
static int window_copy_search_marks(struct window_mode_entry *, |
static int window_copy_search_marks(struct window_mode_entry *, |
struct screen *, int, int); |
struct screen *, int, int); |
static void window_copy_clear_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 int window_copy_is_lowercase(const char *); |
static void window_copy_search_back_overlap(struct grid *, regex_t *, |
static void window_copy_search_back_overlap(struct grid *, regex_t *, |
u_int *, u_int *, u_int *, u_int); |
u_int *, u_int *, u_int *, u_int); |
static int window_copy_search_jump(struct window_mode_entry *, |
static int window_copy_search_jump(struct window_mode_entry *, |
struct grid *, struct grid *, u_int, u_int, u_int, int, int, |
struct grid *, struct grid *, u_int, u_int, u_int, int, int, |
int, int, u_int *); |
int, int); |
static int window_copy_search(struct window_mode_entry *, 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, int); |
static int window_copy_search_up(struct window_mode_entry *, int); |
static int window_copy_search_down(struct window_mode_entry *, int, 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_goto_line(struct window_mode_entry *, const char *); |
static void window_copy_update_cursor(struct window_mode_entry *, u_int, |
static void window_copy_update_cursor(struct window_mode_entry *, u_int, |
u_int); |
u_int); |
|
|
int showmark; |
int showmark; |
|
|
int searchtype; |
int searchtype; |
|
int searchdirection; |
int searchregex; |
int searchregex; |
char *searchstr; |
char *searchstr; |
u_char *searchmark; |
u_char *searchmark; |
|
|
|
|
if (data->searchtype == WINDOW_COPY_SEARCHUP) { |
if (data->searchtype == WINDOW_COPY_SEARCHUP) { |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_up(wme, data->searchregex, 1); |
window_copy_search_up(wme, data->searchregex); |
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { |
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_down(wme, data->searchregex, 1); |
window_copy_search_down(wme, data->searchregex); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
|
|
if (data->searchtype == WINDOW_COPY_SEARCHUP) { |
if (data->searchtype == WINDOW_COPY_SEARCHUP) { |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_down(wme, data->searchregex, 1); |
window_copy_search_down(wme, data->searchregex); |
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { |
} else if (data->searchtype == WINDOW_COPY_SEARCHDOWN) { |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_up(wme, data->searchregex, 1); |
window_copy_search_up(wme, data->searchregex); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
data->searchregex = 1; |
data->searchregex = 1; |
data->timeout = 0; |
data->timeout = 0; |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_up(wme, 1, 0); |
window_copy_search_up(wme, 1); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
data->timeout = 0; |
data->timeout = 0; |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_up(wme, 0, 0); |
window_copy_search_up(wme, 0); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
data->searchregex = 1; |
data->searchregex = 1; |
data->timeout = 0; |
data->timeout = 0; |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_down(wme, 1, 0); |
window_copy_search_down(wme, 1); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
data->timeout = 0; |
data->timeout = 0; |
for (; np != 0; np--) |
for (; np != 0; np--) |
window_copy_search_down(wme, 0, 0); |
window_copy_search_down(wme, 0); |
} |
} |
return (WINDOW_COPY_CMD_NOTHING); |
return (WINDOW_COPY_CMD_NOTHING); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
free(data->searchstr); |
free(data->searchstr); |
data->searchstr = xstrdup(argument); |
data->searchstr = xstrdup(argument); |
if (!window_copy_search_up(wme, 0, 1)) { |
if (!window_copy_search_up(wme, 0)) { |
window_copy_clear_marks(wme); |
window_copy_clear_marks(wme); |
return (WINDOW_COPY_CMD_REDRAW); |
return (WINDOW_COPY_CMD_REDRAW); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
free(data->searchstr); |
free(data->searchstr); |
data->searchstr = xstrdup(argument); |
data->searchstr = xstrdup(argument); |
if (!window_copy_search_down(wme, 0, 0)) { |
if (!window_copy_search_down(wme, 0)) { |
window_copy_clear_marks(wme); |
window_copy_clear_marks(wme); |
return (WINDOW_COPY_CMD_REDRAW); |
return (WINDOW_COPY_CMD_REDRAW); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
free(data->searchstr); |
free(data->searchstr); |
data->searchstr = xstrdup(argument); |
data->searchstr = xstrdup(argument); |
if (!window_copy_search_down(wme, 0, 1)) { |
if (!window_copy_search_down(wme, 0)) { |
window_copy_clear_marks(wme); |
window_copy_clear_marks(wme); |
return (WINDOW_COPY_CMD_REDRAW); |
return (WINDOW_COPY_CMD_REDRAW); |
} |
} |
|
|
data->searchregex = 0; |
data->searchregex = 0; |
free(data->searchstr); |
free(data->searchstr); |
data->searchstr = xstrdup(argument); |
data->searchstr = xstrdup(argument); |
if (!window_copy_search_up(wme, 0, 1)) { |
if (!window_copy_search_up(wme, 0)) { |
window_copy_clear_marks(wme); |
window_copy_clear_marks(wme); |
return (WINDOW_COPY_CMD_REDRAW); |
return (WINDOW_COPY_CMD_REDRAW); |
} |
} |
|
|
*fx = *fx - 1; |
*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 |
static int |
window_copy_is_lowercase(const char *ptr) |
window_copy_is_lowercase(const char *ptr) |
{ |
{ |
|
|
static int |
static int |
window_copy_search_jump(struct window_mode_entry *wme, struct grid *gd, |
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, |
struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap, |
int direction, int regex, u_int *foundlen) |
int direction, int regex) |
{ |
{ |
u_int i, px, sx, ssize = 1; |
u_int i, px, sx, ssize = 1; |
int found = 0, cflags = REG_EXTENDED; |
int found = 0, cflags = REG_EXTENDED; |
|
|
if (regex) { |
if (regex) { |
found = window_copy_search_lr_regex(gd, |
found = window_copy_search_lr_regex(gd, |
&px, &sx, i, fx, gd->sx, ®); |
&px, &sx, i, fx, gd->sx, ®); |
if (found) |
|
*foundlen = sx; |
|
} else { |
} else { |
found = window_copy_search_lr(gd, sgd, |
found = window_copy_search_lr(gd, sgd, |
&px, i, fx, gd->sx, cis); |
&px, i, fx, gd->sx, cis); |
if (found) |
|
*foundlen = sgd->sx; |
|
} |
} |
if (found) |
if (found) |
break; |
break; |
fx = 0; |
fx = 0; |
} |
} |
} else { |
} else { |
*foundlen = 0; |
|
for (i = fy + 1; endline < i; i--) { |
for (i = fy + 1; endline < i; i--) { |
if (regex) { |
if (regex) { |
found = window_copy_search_rl_regex(gd, |
found = window_copy_search_rl_regex(gd, |
|
|
return (window_copy_search_jump(wme, gd, sgd, |
return (window_copy_search_jump(wme, gd, sgd, |
direction ? 0 : gd->sx - 1, |
direction ? 0 : gd->sx - 1, |
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0, |
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0, |
direction, regex, foundlen)); |
direction, regex)); |
} |
} |
return (0); |
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 |
* Search in for text searchstr. If direction is 0 then search up, otherwise |
* down. |
* down. |
*/ |
*/ |
static int |
static int |
window_copy_search(struct window_mode_entry *wme, int direction, int regex, |
window_copy_search(struct window_mode_entry *wme, int direction, int regex) |
int again) |
|
{ |
{ |
struct window_pane *wp = wme->wp; |
struct window_pane *wp = wme->wp; |
struct window_copy_mode_data *data = wme->data; |
struct window_copy_mode_data *data = wme->data; |
|
|
struct screen_write_ctx ctx; |
struct screen_write_ctx ctx; |
struct grid *gd = s->grid; |
struct grid *gd = s->grid; |
const char *str = data->searchstr; |
const char *str = data->searchstr; |
u_int fx, fy, endline, i, foundlen; |
u_int at, endline, fx, fy, start; |
int wrapflag, cis, found, visible_only; |
int cis, found, keys, visible_only; |
|
int wrapflag; |
|
|
if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0') |
if (regex && str[strcspn(str, "^$*+()?[].\\")] == '\0') |
regex = 0; |
regex = 0; |
|
|
|
data->searchdirection = direction; |
|
|
if (data->timeout) |
if (data->timeout) |
return (0); |
return (0); |
|
|
|
|
wrapflag = options_get_number(wp->window->options, "wrap-search"); |
wrapflag = options_get_number(wp->window->options, "wrap-search"); |
cis = window_copy_is_lowercase(str); |
cis = window_copy_is_lowercase(str); |
|
|
if (direction) |
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; |
endline = gd->hsize + gd->sy - 1; |
|
} |
else { |
else { |
if (again) |
window_copy_move_left(s, &fx, &fy, wrapflag); |
window_copy_move_left(s, &fx, &fy, wrapflag); |
|
endline = 0; |
endline = 0; |
} |
} |
|
|
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis, |
found = window_copy_search_jump(wme, gd, ss.grid, fx, fy, endline, cis, |
wrapflag, direction, regex, &foundlen); |
wrapflag, direction, regex); |
if (found) { |
if (found) { |
window_copy_search_marks(wme, &ss, regex, visible_only); |
window_copy_search_marks(wme, &ss, regex, visible_only); |
if (foundlen != 0) { |
fx = data->cx; |
/* Adjust for wrapped lines eating one right. */ |
fy = screen_hsize(data->backing) - data->oy + data->cy; |
i = data->cx + foundlen; |
|
while (i > gd->sx - 1) { |
/* |
i -= gd->sx; |
* When searching forward, if the cursor is not at the beginning |
window_copy_cursor_right(wme, 1); |
* 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; |
} |
} |
for (i = 0; i < foundlen; i++) |
|
window_copy_cursor_right(wme, 1); |
|
} |
} |
|
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); |
window_copy_redraw_screen(wme); |
|
|
|
|
} |
} |
|
|
static int |
static int |
window_copy_search_up(struct window_mode_entry *wme, int regex, int again) |
window_copy_search_up(struct window_mode_entry *wme, int regex) |
{ |
{ |
return (window_copy_search(wme, 0, regex, again)); |
return (window_copy_search(wme, 0, regex)); |
} |
} |
|
|
static int |
static int |
window_copy_search_down(struct window_mode_entry *wme, int regex, int again) |
window_copy_search_down(struct window_mode_entry *wme, int regex) |
{ |
{ |
return (window_copy_search(wme, 1, regex, again)); |
return (window_copy_search(wme, 1, regex)); |
} |
} |
|
|
static void |
static void |
|
|
struct grid_cell *gc, const struct grid_cell *mgc, |
struct grid_cell *gc, const struct grid_cell *mgc, |
const struct grid_cell *cgc, const struct grid_cell *mkgc) |
const struct grid_cell *cgc, const struct grid_cell *mkgc) |
{ |
{ |
|
struct window_pane *wp = wme->wp; |
struct window_copy_mode_data *data = wme->data; |
struct window_copy_mode_data *data = wme->data; |
u_int mark, start, end, cy, cursor, current; |
u_int mark, start, end, cy, cursor, current; |
int inv = 0, found = 0; |
int inv = 0, found = 0; |
|
int keys; |
|
|
if (data->showmark && fy == data->my) { |
if (data->showmark && fy == data->my) { |
gc->attr = mkgc->attr; |
gc->attr = mkgc->attr; |
|
|
|
|
cy = screen_hsize(data->backing) - data->oy + data->cy; |
cy = screen_hsize(data->backing) - data->oy + data->cy; |
if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) { |
if (window_copy_search_mark_at(data, data->cx, cy, &cursor) == 0) { |
if (data->searchmark[cursor] == mark) |
keys = options_get_number(wp->window->options, "mode-keys"); |
found = 1; |
if (cursor != 0 && |
else if (cursor != 0) { |
keys == MODEKEY_EMACS && |
cursor--; |
data->searchdirection) { |
if (data->searchmark[cursor] == mark) |
if (data->searchmark[cursor - 1] == mark) { |
|
cursor--; |
found = 1; |
found = 1; |
} |
} |
|
} else if (data->searchmark[cursor] == mark) |
|
found = 1; |
if (found) { |
if (found) { |
window_copy_match_start_end(data, cursor, &start, &end); |
window_copy_match_start_end(data, cursor, &start, &end); |
if (current >= start && current <= end) { |
if (current >= start && current <= end) { |