mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
search/render: initial support for highlighting all visible matches
Before this patch, only the currently “selected” match was highlighted (by having the “selected” attribute, and by *not* dimming it, like the rest of the grid during a scrollback search). With this patch, we now highlight matches within the viewport. While searching, only the “primary” match is searched-for, and tracked. Then, when rendering a frame, we find all “secondary” matches as well. “holes” are added to the search-mode overlay by the means of an search-match iterator. The iterator’s text matching logic is *very* similar to what we do when the search criteria has been updated, and we re-search the scrollback. It should be possible to refactor this, and share code.
This commit is contained in:
parent
78fcdc5787
commit
90c91d6148
3 changed files with 117 additions and 11 deletions
36
render.c
36
render.c
|
|
@ -35,6 +35,7 @@
|
|||
#include "hsl.h"
|
||||
#include "ime.h"
|
||||
#include "quirks.h"
|
||||
#include "search.h"
|
||||
#include "selection.h"
|
||||
#include "shm.h"
|
||||
#include "sixel.h"
|
||||
|
|
@ -1539,17 +1540,30 @@ render_overlay(struct terminal *term)
|
|||
|
||||
pixman_region32_clear(see_through);
|
||||
|
||||
struct grid *grid = term->grid;
|
||||
for (int r = 0; r < term->rows; r++) {
|
||||
struct row *row = grid_row_in_view(grid, r);
|
||||
int y = term->margins.top + r * term->cell_height;
|
||||
for (int c = 0; c < term->cols; c++) {
|
||||
if (row->cells[c].attrs.selected) {
|
||||
int x = term->margins.left + c * term->cell_width;
|
||||
pixman_region32_union_rect(
|
||||
see_through, see_through,
|
||||
x, y, term->cell_width, term->cell_height);
|
||||
}
|
||||
struct search_match_iterator iter = search_matches_new_iter(term);
|
||||
|
||||
for (struct range match = search_matches_next(&iter);
|
||||
match.start.row >= 0;
|
||||
match = search_matches_next(&iter))
|
||||
{
|
||||
int r = match.start.row;
|
||||
int start_col = match.start.col;
|
||||
const int end_row = match.end.row;
|
||||
|
||||
while (true) {
|
||||
const int end_col =
|
||||
r == end_row ? match.end.col : term->cols - 1;
|
||||
|
||||
int x = term->margins.left + start_col * term->cell_width;
|
||||
int y = term->margins.top + r * term->cell_height;
|
||||
int width = (end_col + 1 - start_col) * term->cell_width;
|
||||
int height = 1 * term->cell_height;
|
||||
|
||||
pixman_region32_union_rect(
|
||||
see_through, see_through, x, y, width, height);
|
||||
|
||||
if (++r > end_row)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
84
search.c
84
search.c
|
|
@ -409,6 +409,90 @@ search_find_next(struct terminal *term)
|
|||
#undef ROW_DEC
|
||||
}
|
||||
|
||||
struct search_match_iterator
|
||||
search_matches_new_iter(struct terminal *term)
|
||||
{
|
||||
return (struct search_match_iterator){
|
||||
.term = term,
|
||||
.start = {0, 0},
|
||||
};
|
||||
}
|
||||
|
||||
struct range
|
||||
search_matches_next(struct search_match_iterator *iter)
|
||||
{
|
||||
xassert(iter->start.row >= 0);
|
||||
xassert(iter->start.col >= 0);
|
||||
|
||||
struct terminal *term = iter->term;
|
||||
//xassert(term->is_searching);
|
||||
|
||||
if (term->search.match_len == 0)
|
||||
goto done;
|
||||
|
||||
int start_col = iter->start.col;
|
||||
|
||||
for (int r = iter->start.row; r < term->rows; r++) {
|
||||
const struct row *row = grid_row_in_view(term->grid, r);
|
||||
|
||||
for (int c = start_col; c < term->cols; c++) {
|
||||
if (matches_cell(term, &row->cells[c], 0) < 0)
|
||||
continue;
|
||||
|
||||
struct range match = {
|
||||
.start = {c, r},
|
||||
.end = {-1, -1},
|
||||
};
|
||||
size_t match_len = 0;
|
||||
|
||||
for (size_t i = 0; i < term->search.len;) {
|
||||
if (c >= term->cols) {
|
||||
if (++r >= term->rows)
|
||||
break;
|
||||
|
||||
row = grid_row_in_view(term->grid, r);
|
||||
c = 0;
|
||||
}
|
||||
|
||||
if (row->cells[c].wc >= CELL_SPACER) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ssize_t additional_chars = matches_cell(term, &row->cells[c], i);
|
||||
if (additional_chars < 0)
|
||||
break;
|
||||
|
||||
i += additional_chars;
|
||||
match_len += additional_chars;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (match_len != term->search.len) {
|
||||
/* Didn't match (completely) */
|
||||
continue;
|
||||
}
|
||||
|
||||
match.end = (struct coord){c - 1, r};
|
||||
|
||||
LOG_DBG("match at %dx%d-%dx%d",
|
||||
match.start.row, match.start.col,
|
||||
match.end.row, match.end.col);
|
||||
|
||||
iter->start.row = r;
|
||||
iter->start.col = c;
|
||||
return match;
|
||||
}
|
||||
|
||||
start_col = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
iter->start.row = -1;
|
||||
iter->start.col = -1;
|
||||
return (struct range){{-1, -1}, {-1, -1}};
|
||||
}
|
||||
|
||||
static void
|
||||
add_wchars(struct terminal *term, char32_t *src, size_t count)
|
||||
{
|
||||
|
|
|
|||
8
search.h
8
search.h
|
|
@ -14,3 +14,11 @@ void search_input(
|
|||
void search_add_chars(struct terminal *term, const char *text, size_t len);
|
||||
|
||||
void search_selection_cancelled(struct terminal *term);
|
||||
|
||||
struct search_match_iterator {
|
||||
struct terminal *term;
|
||||
struct coord start;
|
||||
};
|
||||
|
||||
struct search_match_iterator search_matches_new_iter(struct terminal *term);
|
||||
struct range search_matches_next(struct search_match_iterator *iter);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue