Hi Felix, I didn't have time to work on this, last few months were really busy. I will try to rebase my changes on top of current revision and test them before sending the code again. I hope I will find some time before the end of year.
Cheers Lukas On 1 Nov 2014 00:42, "Felix Rosencrantz" <f.rosencra...@gmail.com> wrote: > Was there any follow up to this thread? Incremental search would be a > great feature to have and is on the TODO list. > > Thanks. > -FR > > On Fri, Aug 8, 2014 at 11:21 AM, Nicholas Marriott < > nicholas.marri...@gmail.com> wrote: > >> Hi >> >> Your mailer has mangled the diffs, if you can't fix it so it works >> inline please send them as attachments instead. >> >> On Mon, Aug 04, 2014 at 07:47:28PM -0700, ??ukasz Pi??tkowski wrote: >> > I have split up my changes into 3 diffs, first is refactoring search >> code >> > in window-copy.c, second is adding incremental search and the last >> one is >> > adding search highlighting. >> > Cheers >> > Lukas >> > -- >> > >> I**am**providing**code**in**this**repository**to**you**under**an**open**source**license.**Because**this**is**my**personal >> > >> repository,**the**license**you**receive**to**my**code**is**from**me**and**not**from**my**employer**(Facebook). >> >> All contributions must be under the ISC license that is at the top of >> each file you modify. >> >> Thanks >> >> > -- >> > Refactor window-copy search functions >> > ============================ >> > diff --git window-copy.c window-copy.c >> > index 0775bcb..1213380 100644 >> > --- window-copy.c >> > +++ window-copy.c >> > @@ -47,8 +47,16 @@ int window_copy_search_lr( >> > ** ** **struct grid *, struct grid *, u_int *, u_int, u_int, >> u_int, >> > int); >> > **int window_copy_search_rl( >> > ** ** **struct grid *, struct grid *, u_int *, u_int, u_int, >> u_int, >> > int); >> > -void window_copy_search_up(struct window_pane *, const char *); >> > -void window_copy_search_down(struct window_pane *, const char *); >> > +void window_copy_move_coordinates( >> > + ** **struct screen *, u_int *, u_int *, const int); >> > +int window_copy_is_lowercase(const char *); >> > +void window_copy_jump_to_searched_string( >> > + ** **struct window_pane *, struct grid *, struct grid *, >> u_int, >> > u_int, >> > + ** **u_int, int, int, const int); >> > +void window_copy_search(struct window_pane *, const char *, >> > + ** **const int, const int); >> > +void window_copy_search_up(struct window_pane *, const char *, >> const >> > int); >> > +void window_copy_search_down(struct window_pane *, const char *, >> const >> > int); >> > **void window_copy_goto_line(struct window_pane *, const char *); >> > **void window_copy_update_cursor(struct window_pane *, u_int, >> u_int); >> > **void window_copy_start_selection(struct window_pane *); >> > @@ -685,12 +693,12 @@ window_copy_key(struct window_pane *wp, struct >> > session *sess, int key) >> > ** if (cmd == MODEKEYCOPY_SEARCHAGAIN) { >> > ** for (; np != 0; np--) { >> > ** window_copy_search_up( >> > - ** **wp, data->searchstr); >> > + wp, data->searchstr, >> 1); >> > ** } >> > ** } else { >> > ** for (; np != 0; np--) { >> > ** window_copy_search_down( >> > - ** **wp, data->searchstr); >> > + wp, data->searchstr, >> 1); >> > ** } >> > ** } >> > ** break; >> > @@ -698,12 +706,12 @@ window_copy_key(struct window_pane *wp, struct >> > session *sess, int key) >> > ** if (cmd == MODEKEYCOPY_SEARCHAGAIN) { >> > ** for (; np != 0; np--) { >> > ** window_copy_search_down( >> > - ** **wp, data->searchstr); >> > + wp, data->searchstr, >> 1); >> > ** } >> > ** } else { >> > ** for (; np != 0; np--) { >> > ** window_copy_search_up( >> > - ** **wp, data->searchstr); >> > + wp, data->searchstr, >> 1); >> > ** } >> > ** } >> > ** break; >> > @@ -811,16 +819,16 @@ window_copy_key_input(struct window_pane *wp, >> int >> > key) >> > ** case WINDOW_COPY_NUMERICPREFIX: >> > ** break; >> > ** case WINDOW_COPY_SEARCHUP: >> > - for (; np != 0; np--) >> > - window_copy_search_up(wp, >> data->inputstr); >> > ** data->searchtype = data->inputtype; >> > ** data->searchstr = xstrdup(data->inputstr); >> > + for (; np != 0; np--) >> > + window_copy_search_up(wp, >> data->inputstr, >> > 0); >> > ** break; >> > ** case WINDOW_COPY_SEARCHDOWN: >> > - for (; np != 0; np--) >> > - window_copy_search_down(wp, >> > data->inputstr); >> > ** data->searchtype = data->inputtype; >> > ** data->searchstr = xstrdup(data->inputstr); >> > + for (; np != 0; np--) >> > + window_copy_search_down(wp, >> > data->inputstr, 0); >> > ** break; >> > ** case WINDOW_COPY_NAMEDBUFFER: >> > ** window_copy_copy_selection(wp, >> data->inputstr); >> > @@ -1033,88 +1041,97 @@ window_copy_search_rl(struct grid *gd, >> > ** return (0); >> > **} >> > +/* For direction == 0 move left, otherwise right; jump line if >> needed */ >> > **void >> > -window_copy_search_up(struct window_pane *wp, const char *searchstr) >> > +window_copy_move_coordinates(struct screen *s, >> > + u_int *fx, u_int *fy, const int direction) >> > **{ >> > - struct window_copy_mode_data *data = wp->modedata; >> > - struct screen *s = data->backing, ss; >> > - struct screen_write_ctx ctx; >> > - struct grid *gd = s->grid, *sgd; >> > - struct grid_cell gc; >> > - size_t searchlen; >> > - u_int i, last, fx, fy, px; >> > - int utf8flag, n, wrapped, >> wrapflag, >> > cis; >> > - const char *ptr; >> > - >> > - if (*searchstr == '\0') >> > - return; >> > - utf8flag = options_get_number(&wp->window->options, "utf8"); >> > - wrapflag = options_get_number(&wp->window->options, >> > "wrap-search"); >> > - searchlen = screen_write_strlen(utf8flag, "%s", searchstr); >> > - >> > - screen_init(&ss, searchlen, 1, 0); >> > - screen_write_start(&ctx, NULL, &ss); >> > - memcpy(&gc, &grid_default_cell, sizeof gc); >> > - screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr); >> > - screen_write_stop(&ctx); >> > - >> > - fx = data->cx; >> > - fy = gd->hsize - data->oy + data->cy; >> > - >> > - if (fx == 0) { >> > - if (fy == 0) >> > + /* If on left/right border */ >> > + if (*fx == (direction ? screen_size_x(s) - 1 : 0)) { >> > + /* If on top/bottom border */ >> > + if (*fy == (direction ? screen_hsize(s) + >> screen_size_y(s) >> > : 0)) >> > + /* Nowhere to go */ >> > ** return; >> > - fx = gd->sx - 1; >> > - fy--; >> > - } else >> > - fx--; >> > - n = wrapped = 0; >> > + /* Jump to beggin/end of lower/upper line */ >> > + *fx = direction ? 0 : screen_size_x(s) - 1; >> > + *fy = direction ? *fy + 1 : *fy - 1; >> > + } else { >> > + *fx = direction ? *fx + 1 : *fx - 1; >> > + } >> > +} >> > - cis = 1; >> > - for (ptr = searchstr; *ptr != '\0'; ptr++) { >> > +int >> > +window_copy_is_lowercase(const char *ptr) >> > +{ >> > + while (*ptr != '\0') { >> > ** if (*ptr != tolower((u_char)*ptr)) { >> > - cis = 0; >> > - break; >> > + return 0; >> > ** } >> > + ++ptr; >> > ** } >> > + return 1; >> > +} >> > -retry: >> > - sgd = ss.grid; >> > - for (i = fy + 1; i > 0; i--) { >> > - last = screen_size_x(s); >> > - if (i == fy + 1) >> > - last = fx; >> > - n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, >> last, >> > cis); >> > - if (n) { >> > - window_copy_scroll_to(wp, px, i - 1); >> > - break; >> > +/* Search in grid `gd` for text stored in grid `sgd` starting from >> > position >> > + * (`fx`, `fy`) up to line `endline` and if found then jump to it. >> > + * If `cis` do it case-insensitive. >> > + * `direction` 0 for searching up, down otherwise >> > + * If `wrap` then go to begin/end of grid and try again up to line >> `fy` >> > */ >> > +void >> > +window_copy_jump_to_searched_string(struct window_pane *wp, >> > + ** **struct grid *gd, struct grid *sgd, u_int fx, u_int fy, >> > + ** **u_int endline, int cis, int wrap, const int direction) >> > +{ >> > + u_int i, px; >> > + int firstIteration, found; >> > + >> > + firstIteration = 1; >> > + if (direction) { >> > + for (i = fy; i <= endline; ++i) { >> > + found = window_copy_search_lr(gd, sgd, &px, >> i, >> > + firstIteration ? fx : 0, gd->sx, >> cis); >> > + if (found) break; >> > + firstIteration = 0; >> > + } >> > + } else { >> > + for (i = fy + 1; endline < i; --i) { >> > + found = window_copy_search_rl(gd, sgd, &px, >> i - 1, >> > + 0, firstIteration ? fx : gd->sx, >> cis); >> > + if (found) { >> > + --i; >> > + break; >> > + } >> > + firstIteration = 0; >> > ** } >> > ** } >> > - if (wrapflag && !n && !wrapped) { >> > - fx = gd->sx - 1; >> > - fy = gd->hsize + gd->sy - 1; >> > - wrapped = 1; >> > - goto retry; >> > + if (found) { >> > + window_copy_scroll_to(wp, px, i); >> > + } else if (wrap) { >> > + /* Start searching from begin/end of grid up to `fy` >> line >> > */ >> > + window_copy_jump_to_searched_string(wp, gd, sgd, >> > + direction ? 0 : gd->sx - 1, >> > + direction ? 0 : gd->hsize + gd->sy - 1, >> > + fy, cis, 0, direction); >> > ** } >> > - >> > - screen_free(&ss); >> > **} >> > **void >> > -window_copy_search_down(struct window_pane *wp, const char >> *searchstr) >> > +window_copy_search(struct window_pane *wp, >> > + ** **const char *searchstr, const int direction, const int move) >> > **{ >> > ** struct window_copy_mode_data *data = wp->modedata; >> > ** struct screen *s = data->backing, ss; >> > ** struct screen_write_ctx ctx; >> > - struct grid *gd = s->grid, *sgd; >> > - struct grid_cell gc; >> > + struct grid *gd = s->grid; >> > + struct grid_cell gc; >> > ** size_t searchlen; >> > - u_int i, first, fx, fy, px; >> > - int utf8flag, n, wrapped, >> wrapflag, >> > cis; >> > - const char *ptr; >> > + u_int fx, fy; >> > + int utf8flag, wrapflag, cis; >> > + >> > + /* current cursor coordinates */ >> > + fx = data->cx; >> > + fy = screen_hsize(data->backing) - data->oy + data->cy; >> > - if (*searchstr == '\0') >> > - return; >> > ** utf8flag = options_get_number(&wp->window->options, "utf8"); >> > ** wrapflag = options_get_number(&wp->window->options, >> > "wrap-search"); >> > ** searchlen = screen_write_strlen(utf8flag, "%s", searchstr); >> > @@ -1125,50 +1142,35 @@ window_copy_search_down(struct window_pane >> *wp, >> > const char *searchstr) >> > ** screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr); >> > ** screen_write_stop(&ctx); >> > - fx = data->cx; >> > - fy = gd->hsize - data->oy + data->cy; >> > - >> > - if (fx == gd->sx - 1) { >> > - if (fy == gd->hsize + gd->sy) >> > - return; >> > - fx = 0; >> > - fy++; >> > - } else >> > - fx++; >> > - n = wrapped = 0; >> > - >> > - cis = 1; >> > - for (ptr = searchstr; *ptr != '\0'; ptr++) { >> > - if (*ptr != tolower((u_char)*ptr)) { >> > - cis = 0; >> > - break; >> > - } >> > + if (move) { >> > + window_copy_move_coordinates(s, &fx, &fy, direction); >> > ** } >> > -retry: >> > - sgd = ss.grid; >> > - for (i = fy + 1; i < gd->hsize + gd->sy + 1; i++) { >> > - first = 0; >> > - if (i == fy + 1) >> > - first = fx; >> > - n = window_copy_search_lr(gd, sgd, &px, i - 1, first, >> > gd->sx, >> > - ** **cis); >> > - if (n) { >> > - window_copy_scroll_to(wp, px, i - 1); >> > - break; >> > - } >> > - } >> > - if (wrapflag && !n && !wrapped) { >> > - fx = 0; >> > - fy = 0; >> > - wrapped = 1; >> > - goto retry; >> > - } >> > + cis = window_copy_is_lowercase(searchstr); >> > + window_copy_clear_selection(wp); >> > + >> > + window_copy_jump_to_searched_string(wp, gd, ss.grid, fx, fy, >> > + direction ? gd->hsize + gd->sy - 1 : 0, >> > + cis, wrapflag, direction); >> > ** screen_free(&ss); >> > **} >> > **void >> > +window_copy_search_up(struct window_pane *wp, const char *searchstr, >> > + const int move) >> > +{ >> > + window_copy_search(wp, searchstr, 0, move); >> > +} >> > + >> > +void >> > +window_copy_search_down(struct window_pane *wp, const char >> *searchstr, >> > + const int move) >> > +{ >> > + window_copy_search(wp, searchstr, 1, move); >> > +} >> > + >> > +void >> > **window_copy_goto_line(struct window_pane *wp, const char *linestr) >> > **{ >> > ** struct window_copy_mode_data *data = wp->modedata; >> > Incremental search in window-copy mode >> > ============================== >> > diff --git window-copy.c window-copy.c >> > index 1213380..243c755 100644 >> > --- window-copy.c >> > +++ window-copy.c >> > @@ -53,6 +53,9 @@ int window_copy_is_lowercase(const char *); >> > **void window_copy_jump_to_searched_string( >> > ** ** **struct window_pane *, struct grid *, struct grid *, >> u_int, >> > u_int, >> > ** ** **u_int, int, int, const int); >> > +int window_copy_coord_from_hist(struct window_pane *wp, >> > + ** **const size_t searchlen, u_int *fx, u_int *fy); >> > +void window_copy_clear_search_hist(struct window_pane *, u_int *, >> u_int >> > *); >> > **void window_copy_search(struct window_pane *, const char *, >> > ** ** **const int, const int); >> > **void window_copy_search_up(struct window_pane *, const char *, >> const >> > int); >> > @@ -115,6 +118,22 @@ enum window_copy_input_type { >> > **}; >> > **/* >> > + * x, y - coordinates from which the search was made >> > + * found - if the text was found >> > + * searchlen - lenght of text that was searched >> > + * prev - data of previous searches >> > + */ >> > +struct window_copy_search_hist { >> > + u_int x; >> > + u_int y; >> > + int found; >> > + >> > + size_t searchlen; >> > + >> > + struct window_copy_search_hist ***prev; >> > +}; >> > + >> > +/* >> > ** * Copy-mode's visible screen (the "screen" field) is filled from >> one of >> > ** * two sources: the original contents of the pane (used when we >> > ** * actually enter via the "copy-mode" command, to copy the >> contents of >> > @@ -159,6 +178,7 @@ struct window_copy_mode_data { >> > ** enum window_copy_input_type searchtype; >> > ** char ** ** ** *searchstr; >> > + struct window_copy_search_hist *searchhist; >> > ** enum window_copy_input_type jumptype; >> > ** char jumpchar; >> > @@ -190,6 +210,7 @@ window_copy_init(struct window_pane *wp) >> > ** data->searchtype = WINDOW_COPY_OFF; >> > ** data->searchstr = NULL; >> > + data->searchhist = NULL; >> > ** if (wp->fd != -1) >> > ** bufferevent_disable(wp->event, EV_READ|EV_WRITE); >> > @@ -259,6 +280,7 @@ window_copy_free(struct window_pane *wp) >> > ** free(data->searchstr); >> > ** free(data->inputstr); >> > + window_copy_clear_search_hist(wp, NULL, NULL); >> > ** if (data->backing != &wp->base) { >> > ** screen_free(data->backing); >> > @@ -672,10 +694,12 @@ window_copy_key(struct window_pane *wp, struct >> > session *sess, int key) >> > ** case MODEKEYCOPY_SEARCHUP: >> > ** data->inputtype = WINDOW_COPY_SEARCHUP; >> > ** data->inputprompt = "Search Up"; >> > + *data->inputstr = '\0'; >> > ** goto input_on; >> > ** case MODEKEYCOPY_SEARCHDOWN: >> > ** data->inputtype = WINDOW_COPY_SEARCHDOWN; >> > ** data->inputprompt = "Search Down"; >> > + *data->inputstr = '\0'; >> > ** goto input_on; >> > ** case MODEKEYCOPY_SEARCHAGAIN: >> > ** case MODEKEYCOPY_SEARCHREVERSE: >> > @@ -778,6 +802,7 @@ window_copy_key_input(struct window_pane *wp, >> int key) >> > ** int np; >> > ** struct paste_buffer *pb; >> > ** u_char ch; >> > + u_int fx, fy; >> > ** switch (mode_key_lookup(&data->mdata, key, NULL)) { >> > ** case MODEKEYEDIT_CANCEL: >> > @@ -787,9 +812,29 @@ window_copy_key_input(struct window_pane *wp, >> int >> > key) >> > ** inputlen = strlen(data->inputstr); >> > ** if (inputlen > 0) >> > ** data->inputstr[inputlen - 1] = '\0'; >> > + switch (data->inputtype) { >> > + case WINDOW_COPY_SEARCHUP: >> > + data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > + data->searchstr = xstrdup(data->inputstr); >> > + window_copy_search_up(wp, data->inputstr, 0); >> > + break; >> > + case WINDOW_COPY_SEARCHDOWN: >> > + data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > + data->searchstr = xstrdup(data->inputstr); >> > + window_copy_search_down(wp, data->inputstr, >> 0); >> > + break; >> > + default: >> > + break; >> > + } >> > ** break; >> > ** case MODEKEYEDIT_DELETELINE: >> > ** *data->inputstr = '\0'; >> > + fx = data->cx; >> > + fy = screen_hsize(data->backing) - data->oy + >> data->cy; >> > + window_copy_clear_search_hist(wp, &fx, &fy); >> > + window_copy_scroll_to(wp, fx, fy); >> > ** break; >> > ** case MODEKEYEDIT_PASTE: >> > ** if ((pb = paste_get_top()) == NULL) >> > @@ -820,15 +865,17 @@ window_copy_key_input(struct window_pane *wp, >> int >> > key) >> > ** break; >> > ** case WINDOW_COPY_SEARCHUP: >> > ** data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > ** data->searchstr = xstrdup(data->inputstr); >> > - for (; np != 0; np--) >> > - window_copy_search_up(wp, >> data->inputstr, >> > 0); >> > + for (; np > 1; np--) >> > + window_copy_search_up(wp, >> data->inputstr, >> > 1); >> > ** break; >> > ** case WINDOW_COPY_SEARCHDOWN: >> > ** data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > ** data->searchstr = xstrdup(data->inputstr); >> > - for (; np != 0; np--) >> > - window_copy_search_down(wp, >> > data->inputstr, 0); >> > + for (; np > 1; np--) >> > + window_copy_search_down(wp, >> > data->inputstr, 1); >> > ** break; >> > ** case WINDOW_COPY_NAMEDBUFFER: >> > ** window_copy_copy_selection(wp, >> data->inputstr); >> > @@ -850,6 +897,22 @@ window_copy_key_input(struct window_pane *wp, >> int >> > key) >> > ** data->inputstr = xrealloc(data->inputstr, 1, >> inputlen); >> > ** data->inputstr[inputlen - 2] = key; >> > ** data->inputstr[inputlen - 1] = '\0'; >> > + switch (data->inputtype) { >> > + case WINDOW_COPY_SEARCHUP: >> > + data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > + data->searchstr = xstrdup(data->inputstr); >> > + window_copy_search_up(wp, data->inputstr, 0); >> > + break; >> > + case WINDOW_COPY_SEARCHDOWN: >> > + data->searchtype = data->inputtype; >> > + free(data->searchstr); >> > + data->searchstr = xstrdup(data->inputstr); >> > + window_copy_search_down(wp, data->inputstr, >> 0); >> > + break; >> > + default: >> > + break; >> > + } >> > ** break; >> > ** default: >> > ** break; >> > @@ -1082,6 +1145,8 @@ window_copy_jump_to_searched_string(struct >> > window_pane *wp, >> > ** ** **struct grid *gd, struct grid *sgd, u_int fx, u_int fy, >> > ** ** **u_int endline, int cis, int wrap, const int direction) >> > **{ >> > + struct window_copy_mode_data *data = wp->modedata; >> > + struct window_copy_search_hist *searchhist = >> data->searchhist; >> > ** u_int i, px; >> > ** int firstIteration, found; >> > @@ -1112,6 +1177,60 @@ window_copy_jump_to_searched_string(struct >> > window_pane *wp, >> > ** direction ? 0 : gd->sx - 1, >> > ** direction ? 0 : gd->hsize + gd->sy - 1, >> > ** fy, cis, 0, direction); >> > + } else { >> > + if (searchhist != NULL) { >> > + searchhist->found = 0; >> > + } >> > + } >> > +} >> > + >> > +/* If it returns 0 then, according to search history, last time we >> > searched >> > + * a shorter string we haven't found anything, so there is no point >> in >> > + * incremental-searching a longer string (just an optimization) */ >> > +int >> > +window_copy_coord_from_hist(struct window_pane *wp, >> > + ** **const size_t searchlen, u_int *fx, u_int *fy) >> > +{ >> > + struct window_copy_mode_data *data = wp->modedata; >> > + struct window_copy_search_hist *searchhist = >> data->searchhist; >> > + >> > + if (searchhist == NULL || searchhist->searchlen < searchlen) >> { >> > + searchhist = xmalloc(sizeof (struct >> > window_copy_search_hist)); >> > + searchhist->x = data->cx; >> > + searchhist->y = >> > + screen_hsize(data->backing) - data->oy + >> data->cy; >> > + searchhist->searchlen = searchlen; >> > + searchhist->found = data->searchhist == NULL ? >> > + 1 : data->searchhist->found; >> > + >> > + searchhist->prev = data->searchhist; >> > + data->searchhist = searchhist; >> > + >> > + *fx = searchhist->x; >> > + *fy = searchhist->y; >> > + } else { >> > + *fx = searchhist->x; >> > + *fy = searchhist->y; >> > + searchhist = data->searchhist->prev; >> > + free(data->searchhist); >> > + data->searchhist = searchhist; >> > + } >> > + >> > + return searchhist == NULL ? 1 : searchhist->found; >> > +} >> > + >> > +void >> > +window_copy_clear_search_hist(struct window_pane *wp, u_int *fx, >> u_int >> > *fy) >> > +{ >> > + struct window_copy_mode_data *data = wp->modedata; >> > + struct window_copy_search_hist *searchhist = >> data->searchhist; >> > + >> > + while (searchhist != NULL) { >> > + if (fx != NULL) *fx = searchhist->x; >> > + if (fy != NULL) *fy = searchhist->y; >> > + searchhist = searchhist->prev; >> > + free(data->searchhist); >> > + data->searchhist = searchhist; >> > ** } >> > **} >> > @@ -1132,6 +1251,14 @@ window_copy_search(struct window_pane *wp, >> > ** fx = data->cx; >> > ** fy = screen_hsize(data->backing) - data->oy + data->cy; >> > + /* User deleted all searched text, jump to the initial cursor >> > + * position and delete the searchhistory */ >> > + if ((searchstr == NULL) || (*searchstr == '\0')) { >> > + window_copy_clear_search_hist(wp, &fx, &fy); >> > + window_copy_scroll_to(wp, fx, fy); >> > + return; >> > + } >> > + >> > ** utf8flag = options_get_number(&wp->window->options, "utf8"); >> > ** wrapflag = options_get_number(&wp->window->options, >> > "wrap-search"); >> > ** searchlen = screen_write_strlen(utf8flag, "%s", searchstr); >> > @@ -1142,8 +1269,19 @@ window_copy_search(struct window_pane *wp, >> > ** screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", searchstr); >> > ** screen_write_stop(&ctx); >> > + /* >> > + * `move` is useful for incremental searching. When we do >> > incremental, >> > + * **we don't want to jump to the next matching word if we >> already >> > stand >> > + * **on one, so `move=0`. >> > + * **But when user wants the next result, then we use >> `move=1`, so >> > + * **we start searching from the place next to the current >> cursor >> > + * **position */ >> > ** if (move) { >> > ** window_copy_move_coordinates(s, &fx, &fy, direction); >> > + } else { >> > + if (!window_copy_coord_from_hist(wp, searchlen, &fx, >> &fy)) >> > { >> > + return; >> > + } >> > ** } >> > ** cis = window_copy_is_lowercase(searchstr); >> > Highlight last search in window-copy mode >> > =============================== >> > diff --git options-table.c options-table.c >> > index 8d680b3..79ecae3 100644 >> > --- options-table.c >> > +++ options-table.c >> > @@ -619,6 +619,11 @@ const struct options_table_entry >> > window_options_table[] = { >> > ** **.default_str = "bg=yellow,fg=black" >> > ** }, >> > + { .name = "highlight-style", >> > + **.type = OPTIONS_TABLE_STYLE, >> > + **.default_str = "bg=green,fg=black" >> > + }, >> > + >> > ** { .name = "monitor-activity", >> > ** **.type = OPTIONS_TABLE_FLAG, >> > ** **.default_num = 0 >> > @@ -802,6 +807,11 @@ const struct options_table_entry >> > window_options_table[] = { >> > ** **.default_num = 1 >> > ** }, >> > + { .name = "highlight-search", >> > + **.type = OPTIONS_TABLE_FLAG, >> > + **.default_num = 1 >> > + }, >> > + >> > ** { .name = "xterm-keys", >> > ** **.type = OPTIONS_TABLE_FLAG, >> > ** **.default_num = 0 >> > diff --git screen-write.c screen-write.c >> > index 325fb9a..a36a1f2 100644 >> > --- screen-write.c >> > +++ screen-write.c >> > @@ -902,7 +902,7 @@ screen_write_cell(struct screen_write_ctx *ctx, >> const >> > struct grid_cell *gc) >> > ** struct grid *gd = s->grid; >> > ** struct tty_ctx ttyctx; >> > ** u_int width, xx, last; >> > - struct grid_cell tmp_gc, *tmp_gcp; >> > + struct grid_cell tmp_gc, *tmp_gcp, *cell = NULL; >> > ** struct utf8_data ud; >> > ** int insert; >> > @@ -995,6 +995,15 @@ screen_write_cell(struct screen_write_ctx *ctx, >> const >> > struct grid_cell *gc) >> > ** ** **(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > ** ttyctx.cell = &tmp_gc; >> > ** tty_write(tty_cmd_cell, &ttyctx); >> > + } else if (screen_check_highlight(s, s->cx - width, s->cy, >> &cell)) >> > { >> > + memcpy(&tmp_gc, cell, sizeof tmp_gc); >> > + grid_cell_get(gc, &ud); >> > + grid_cell_set(&tmp_gc, &ud); >> > + tmp_gc.flags = gc->flags & >> > ~(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > + tmp_gc.flags |= cell->flags & >> > + ** **(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > + ttyctx.cell = &tmp_gc; >> > + tty_write(tty_cmd_cell, &ttyctx); >> > ** } else { >> > ** ttyctx.cell = gc; >> > ** tty_write(tty_cmd_cell, &ttyctx); >> > diff --git screen.c screen.c >> > index 7bfc015..734b38e 100644 >> > --- screen.c >> > +++ screen.c >> > @@ -44,6 +44,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, >> u_int >> > hlimit) >> > ** s->cstyle = 0; >> > ** s->ccolour = xstrdup(""); >> > ** s->tabs = NULL; >> > + s->hls = NULL; >> > ** screen_reinit(s); >> > **} >> > @@ -65,6 +66,7 @@ screen_reinit(struct screen *s) >> > ** grid_clear_lines(s->grid, s->grid->hsize, s->grid->sy); >> > ** screen_clear_selection(s); >> > + screen_clear_highlight(s); >> > **} >> > **/* Destroy a screen. */ >> > @@ -75,6 +77,7 @@ screen_free(struct screen *s) >> > ** free(s->title); >> > ** free(s->ccolour); >> > ** grid_destroy(s->grid); >> > + screen_clear_highlight(s); >> > **} >> > **/* Reset tabs to default, eight spaces apart. */ >> > @@ -357,6 +360,56 @@ screen_check_selection(struct screen *s, u_int >> px, >> > u_int py) >> > ** return (1); >> > **} >> > +/* Set highlight. */ >> > +void >> > +screen_set_highlight(struct screen *s, >> > + u_int sx, u_int ex, u_int y, struct grid_cell *gc) >> > +{ >> > + struct screen_hls *hls = xmalloc(sizeof (struct >> > screen_hls)); >> > + >> > + hls->sx = sx; >> > + hls->ex = ex; >> > + hls->y = y; >> > + hls->next = s->hls; >> > + >> > + memcpy(&hls->cell, gc, sizeof hls->cell); >> > + >> > + s->hls = hls; >> > +} >> > + >> > +/* Clear highlights. */ >> > +void >> > +screen_clear_highlight(struct screen *s) >> > +{ >> > + struct screen_hls *hls = s->hls, *hlsPrev; >> > + >> > + while (hls != NULL) { >> > + hlsPrev = hls; >> > + hls = hls->next; >> > + free(hlsPrev); >> > + } >> > + >> > + s->hls = NULL; >> > +} >> > + >> > +/* Check if cell in highlight. */ >> > +int >> > +screen_check_highlight(struct screen *s, u_int px, u_int py, >> > + struct grid_cell **cell) >> > +{ >> > + struct screen_hls *hls = s->hls; >> > + >> > + while (hls != NULL) { >> > + if (hls->sx <= px && px <= hls->ex && hls->y == py) { >> > + *cell = &hls->cell; >> > + return 1; >> > + } >> > + hls = hls->next; >> > + } >> > + >> > + return 0; >> > +} >> > + >> > **/* Reflow wrapped lines. */ >> > **void >> > **screen_reflow(struct screen *s, u_int new_x) >> > diff --git tmux.h tmux.h >> > index c4c5236..6fc5fd0 100644 >> > --- tmux.h >> > +++ tmux.h >> > @@ -766,6 +766,17 @@ struct screen_sel { >> > ** struct grid_cell cell; >> > **}; >> > +/* Screen highlights. */ >> > +struct screen_hls { >> > + u_int sx; >> > + u_int ex; >> > + >> > + u_int y; >> > + >> > + struct grid_cell cell; >> > + struct screen_hls *next; >> > +}; >> > + >> > **/* Virtual screen. */ >> > **struct screen { >> > ** char *title; >> > @@ -786,6 +797,7 @@ struct screen { >> > ** bitstr_t *tabs; >> > ** struct screen_sel sel; >> > + struct screen_hls *hls; >> > **}; >> > **/* Screen write context. */ >> > @@ -2118,6 +2130,11 @@ void screen_set_selection(struct screen >> *, >> > ** ** ** u_int, u_int, u_int, u_int, u_int, struct grid_cell >> *); >> > **void screen_clear_selection(struct screen *); >> > **int screen_check_selection(struct screen *, u_int, u_int); >> > +void screen_set_highlight(struct screen *, >> > + ** ** u_int, u_int, u_int, struct grid_cell *); >> > +void screen_clear_highlight(struct screen *); >> > +int screen_check_highlight(struct screen *, u_int, u_int, >> > + ** ** struct grid_cell **); >> > **void screen_reflow(struct screen *, u_int); >> > **/* window.c */ >> > diff --git tty.c tty.c >> > index 7688e90..4511533 100644 >> > --- tty.c >> > +++ tty.c >> > @@ -614,7 +614,7 @@ tty_draw_line(struct tty *tty, struct screen *s, >> u_int >> > py, u_int ox, u_int oy) >> > **{ >> > ** const struct grid_cell *gc; >> > ** struct grid_line *gl; >> > - struct grid_cell tmpgc; >> > + struct grid_cell tmpgc, *cell = NULL; >> > ** struct utf8_data ud; >> > ** u_int i, sx; >> > @@ -649,6 +649,15 @@ tty_draw_line(struct tty *tty, struct screen *s, >> > u_int py, u_int ox, u_int oy) >> > ** tmpgc.flags |= s->sel.cell.flags & >> > ** ** **(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > ** tty_cell(tty, &tmpgc); >> > + } else if (screen_check_highlight(s, i, py, &cell)) { >> > + memcpy(&tmpgc, cell, sizeof tmpgc); >> > + grid_cell_get(gc, &ud); >> > + grid_cell_set(&tmpgc, &ud); >> > + tmpgc.flags = gc->flags & >> > + ** **~(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > + tmpgc.flags |= cell->flags & >> > + ** **(GRID_FLAG_FG256|GRID_FLAG_BG256); >> > + tty_cell(tty, &tmpgc); >> > ** } else >> > ** tty_cell(tty, gc); >> > ** } >> > diff --git window-copy.c window-copy.c >> > index 243c755..00cdc3f 100644 >> > --- window-copy.c >> > +++ window-copy.c >> > @@ -28,10 +28,13 @@ struct screen *window_copy_init(struct >> window_pane *); >> > **void window_copy_free(struct window_pane *); >> > **void window_copy_resize(struct window_pane *, u_int, u_int); >> > **void window_copy_key(struct window_pane *, struct session *, int); >> > +void window_copy_key_internal(struct window_pane *, struct >> session *, >> > int); >> > **int window_copy_key_input(struct window_pane *, int); >> > **int window_copy_key_numeric_prefix(struct window_pane *, int); >> > **void window_copy_mouse( >> > ** ** **struct window_pane *, struct session *, struct >> mouse_event >> > *); >> > +void window_copy_mouse_internal( >> > + ** **struct window_pane *, struct session *, struct >> mouse_event >> > *); >> > **void window_copy_redraw_lines(struct window_pane *, u_int, u_int); >> > **void window_copy_redraw_screen(struct window_pane *); >> > @@ -53,6 +56,7 @@ int window_copy_is_lowercase(const char *); >> > **void window_copy_jump_to_searched_string( >> > ** ** **struct window_pane *, struct grid *, struct grid *, >> u_int, >> > u_int, >> > ** ** **u_int, int, int, const int); >> > +void window_copy_highlight_search(struct window_pane *); >> > **int window_copy_coord_from_hist(struct window_pane *wp, >> > ** ** **const size_t searchlen, u_int *fx, u_int *fy); >> > **void window_copy_clear_search_hist(struct window_pane *, u_int *, >> u_int >> > *); >> > @@ -397,6 +401,16 @@ window_copy_resize(struct window_pane *wp, >> u_int sx, >> > u_int sy) >> > **void >> > **window_copy_key(struct window_pane *wp, struct session *sess, int >> key) >> > **{ >> > + window_copy_key_internal(wp, sess, key); >> > + >> > + if (wp->mode != NULL) { >> > + window_copy_highlight_search(wp); >> > + } >> > +} >> > + >> > +void >> > +window_copy_key_internal(struct window_pane *wp, struct session >> *sess, >> > int key) >> > +{ >> > ** const char *word_separators; >> > ** struct window_copy_mode_data *data = wp->modedata; >> > ** struct screen *s = &data->screen; >> > @@ -944,6 +958,17 @@ void >> > **window_copy_mouse( >> > ** ** **struct window_pane *wp, struct session *sess, struct >> mouse_event >> > *m) >> > **{ >> > + window_copy_mouse_internal(wp, sess, m); >> > + >> > + if (wp->mode != NULL) { >> > + window_copy_highlight_search(wp); >> > + } >> > +} >> > + >> > +void >> > +window_copy_mouse_internal( >> > + ** **struct window_pane *wp, struct session *sess, struct >> mouse_event >> > *m) >> > +{ >> > ** struct window_copy_mode_data *data = wp->modedata; >> > ** struct screen *s = &data->screen; >> > ** u_int i; >> > @@ -1184,6 +1209,68 @@ window_copy_jump_to_searched_string(struct >> > window_pane *wp, >> > ** } >> > **} >> > +void >> > +window_copy_highlight_search(struct window_pane *wp) >> > +{ >> > + struct window_copy_mode_data *data = wp->modedata; >> > + struct screen *s = data->backing, ss; >> > + struct screen_write_ctx ctx; >> > + struct grid *gd = s->grid; >> > + struct grid_cell gc; >> > + struct options *oo = &wp->window->options; >> > + const char *searchstr = data->searchstr; >> > + size_t searchlen; >> > + u_int i, px, last, beginline, >> endline; >> > + int found, utf8flag, cis, >> highlight; >> > + >> > + highlight = options_get_number( >> > + &wp->window->options, "highlight-search"); >> > + if (!highlight) { >> > + return; >> > + } >> > + >> > + screen_clear_highlight(&data->screen); >> > + >> > + if ((searchstr != NULL) && (*searchstr != '\0')) { >> > + utf8flag = options_get_number(&wp->window->options, >> > "utf8"); >> > + searchlen = screen_write_strlen(utf8flag, "%s", >> > searchstr); >> > + >> > + screen_init(&ss, searchlen, 1, 0); >> > + screen_write_start(&ctx, NULL, &ss); >> > + memcpy(&gc, &grid_default_cell, sizeof gc); >> > + screen_write_nputs(&ctx, -1, &gc, utf8flag, "%s", >> > searchstr); >> > + screen_write_stop(&ctx); >> > + >> > + cis = window_copy_is_lowercase(searchstr); >> > + >> > + /* Set colours. */ >> > + style_apply(&gc, oo, "highlight-style"); >> > + >> > + beginline = screen_hsize(s) - data->oy; >> > + endline = screen_hsize(s) - data->oy + >> screen_size_y(s) - >> > 1; >> > + >> > + for (i = beginline; i <= endline; ++i) { >> > + last = 0; >> > + do { >> > + found = window_copy_search_lr(gd, >> ss.grid, >> > &px, >> > + i, last, gd->sx, cis); >> > + if (found) { >> > + screen_set_highlight( >> > + &data->screen, >> > + px, >> > + px + searchlen - 1, >> > + i - (screen_hsize(s) >> > + ** ** - data->oy), >> > + &gc); >> > + last += searchlen; >> > + } >> > + } while (found); >> > + } >> > + } >> > + >> > + window_copy_redraw_screen(wp); >> > +} >> > + >> > **/* If it returns 0 then, according to search history, last time we >> > searched >> > ** * a shorter string we haven't found anything, so there is no >> point in >> > ** * incremental-searching a longer string (just an optimization) */ >> >> > >> ------------------------------------------------------------------------------ >> > Want fast and easy access to all the code in your enterprise? Index and >> > search up to 200,000 lines of code with a free copy of Black Duck >> > Code Sight - the same software that powers the world's largest code >> > search on Ohloh, the Black Duck Open Hub! Try it now. >> > http://p.sf.net/sfu/bds >> >> > _______________________________________________ >> > tmux-users mailing list >> > tmux-users@lists.sourceforge.net >> > https://lists.sourceforge.net/lists/listinfo/tmux-users >> >> >> >> ------------------------------------------------------------------------------ >> Want fast and easy access to all the code in your enterprise? Index and >> search up to 200,000 lines of code with a free copy of Black Duck >> Code Sight - the same software that powers the world's largest code >> search on Ohloh, the Black Duck Open Hub! Try it now. >> http://p.sf.net/sfu/bds >> _______________________________________________ >> tmux-users mailing list >> tmux-users@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/tmux-users >> > >
------------------------------------------------------------------------------
_______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users