mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
search: break out “find next match” logic to a new function
This commit is contained in:
parent
90c91d6148
commit
bd089c845f
2 changed files with 101 additions and 113 deletions
211
search.c
211
search.c
|
|
@ -288,58 +288,30 @@ matches_cell(const struct terminal *term, const struct cell *cell, size_t search
|
||||||
return composed != NULL ? 1 + composed->count : 1;
|
return composed != NULL ? 1 + composed->count : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
search_find_next(struct terminal *term)
|
find_next(struct terminal *term, enum search_direction direction,
|
||||||
|
int start_row_abs, int start_col, int row_count,
|
||||||
|
struct range *match)
|
||||||
{
|
{
|
||||||
struct grid *grid = term->grid;
|
|
||||||
bool backward = term->search.direction == SEARCH_BACKWARD;
|
|
||||||
term->search.direction = SEARCH_BACKWARD;
|
|
||||||
|
|
||||||
if (term->search.len == 0) {
|
|
||||||
term->search.match = (struct coord){-1, -1};
|
|
||||||
term->search.match_len = 0;
|
|
||||||
selection_cancel(term);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start_row = term->search.match.row;
|
|
||||||
int start_col = term->search.match.col;
|
|
||||||
size_t len = term->search.match_len;
|
|
||||||
|
|
||||||
xassert((len == 0 && start_row == -1 && start_col == -1) ||
|
|
||||||
(len > 0 && start_row >= 0 && start_col >= 0));
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
if (backward) {
|
|
||||||
start_row = grid_row_absolute_in_view(grid, term->rows - 1);
|
|
||||||
start_col = term->cols - 1;
|
|
||||||
} else {
|
|
||||||
start_row = grid_row_absolute_in_view(grid, 0);
|
|
||||||
start_col = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DBG("search: update: %s: starting at row=%d col=%d (offset = %d, view = %d)",
|
|
||||||
backward ? "backward" : "forward", start_row, start_col,
|
|
||||||
grid->offset, grid->view);
|
|
||||||
|
|
||||||
#define ROW_DEC(_r) ((_r) = ((_r) - 1 + grid->num_rows) & (grid->num_rows - 1))
|
#define ROW_DEC(_r) ((_r) = ((_r) - 1 + grid->num_rows) & (grid->num_rows - 1))
|
||||||
#define ROW_INC(_r) ((_r) = ((_r) + 1) & (grid->num_rows - 1))
|
#define ROW_INC(_r) ((_r) = ((_r) + 1) & (grid->num_rows - 1))
|
||||||
|
|
||||||
/* Scan backward from current end-of-output */
|
struct grid *grid = term->grid;
|
||||||
/* TODO: don't search "scrollback" in alt screen? */
|
const bool backward = direction == SEARCH_BACKWARD;
|
||||||
|
int start_row = start_row_abs;
|
||||||
|
|
||||||
for (size_t r = 0;
|
for (size_t r = 0;
|
||||||
r < grid->num_rows;
|
r < row_count;
|
||||||
backward ? ROW_DEC(start_row) : ROW_INC(start_row), r++)
|
backward ? ROW_DEC(start_row) : ROW_INC(start_row), r++)
|
||||||
{
|
{
|
||||||
|
const struct row *row = grid->rows[start_row];
|
||||||
|
if (row == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (;
|
for (;
|
||||||
backward ? start_col >= 0 : start_col < term->cols;
|
backward ? start_col >= 0 : start_col < term->cols;
|
||||||
backward ? start_col-- : start_col++)
|
backward ? start_col-- : start_col++)
|
||||||
{
|
{
|
||||||
const struct row *row = grid->rows[start_row];
|
|
||||||
if (row == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (matches_cell(term, &row->cells[start_col], 0) < 0)
|
if (matches_cell(term, &row->cells[start_col], 0) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -384,28 +356,76 @@ search_find_next(struct terminal *term)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
*match = (struct range){
|
||||||
* We matched the entire buffer. Move view to ensure the
|
.start = {start_col, start_row},
|
||||||
* match is visible, create a selection and return.
|
.end = {end_col - 1, end_row},
|
||||||
*/
|
};
|
||||||
search_update_selection(term, start_row, start_col, end_row, end_col);
|
|
||||||
|
|
||||||
/* Update match state */
|
return true;
|
||||||
term->search.match.row = start_row;
|
|
||||||
term->search.match.col = start_col;
|
|
||||||
term->search.match_len = match_len;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start_col = backward ? term->cols - 1 : 0;
|
start_col = backward ? term->cols - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No match */
|
return false;
|
||||||
LOG_DBG("no match");
|
}
|
||||||
term->search.match = (struct coord){-1, -1};
|
|
||||||
term->search.match_len = 0;
|
static void
|
||||||
selection_cancel(term);
|
search_find_next(struct terminal *term)
|
||||||
|
{
|
||||||
|
struct grid *grid = term->grid;
|
||||||
|
enum search_direction direction = term->search.direction;
|
||||||
|
const bool backward = term->search.direction == SEARCH_BACKWARD;
|
||||||
|
|
||||||
|
term->search.direction = SEARCH_BACKWARD;
|
||||||
|
|
||||||
|
if (term->search.len == 0) {
|
||||||
|
term->search.match = (struct coord){-1, -1};
|
||||||
|
term->search.match_len = 0;
|
||||||
|
selection_cancel(term);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start_row = term->search.match.row;
|
||||||
|
int start_col = term->search.match.col;
|
||||||
|
size_t len = term->search.match_len;
|
||||||
|
|
||||||
|
xassert((len == 0 && start_row == -1 && start_col == -1) ||
|
||||||
|
(len > 0 && start_row >= 0 && start_col >= 0));
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
if (backward) {
|
||||||
|
start_row = grid_row_absolute_in_view(grid, term->rows - 1);
|
||||||
|
start_col = term->cols - 1;
|
||||||
|
} else {
|
||||||
|
start_row = grid_row_absolute_in_view(grid, 0);
|
||||||
|
start_col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG(
|
||||||
|
"search: update: %s: starting at row=%d col=%d "
|
||||||
|
"(offset = %d, view = %d)",
|
||||||
|
backward ? "backward" : "forward", start_row, start_col,
|
||||||
|
grid->offset, grid->view);
|
||||||
|
|
||||||
|
struct range match;
|
||||||
|
bool found = find_next(
|
||||||
|
term, direction, start_row, start_col, grid->num_rows, &match);
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
search_update_selection(
|
||||||
|
term,
|
||||||
|
match.start.row, match.start.col,
|
||||||
|
match.end.row, match.end.col + 1);
|
||||||
|
term->search.match = match.start;
|
||||||
|
term->search.match_len = term->search.len;
|
||||||
|
} else {
|
||||||
|
LOG_DBG("no match");
|
||||||
|
term->search.match = (struct coord){-1, -1};
|
||||||
|
term->search.match_len = 0;
|
||||||
|
selection_cancel(term);
|
||||||
|
}
|
||||||
#undef ROW_DEC
|
#undef ROW_DEC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,69 +445,36 @@ search_matches_next(struct search_match_iterator *iter)
|
||||||
xassert(iter->start.col >= 0);
|
xassert(iter->start.col >= 0);
|
||||||
|
|
||||||
struct terminal *term = iter->term;
|
struct terminal *term = iter->term;
|
||||||
//xassert(term->is_searching);
|
struct grid *grid = term->grid;
|
||||||
|
|
||||||
if (term->search.match_len == 0)
|
if (term->search.match_len == 0)
|
||||||
goto done;
|
goto no_match;
|
||||||
|
|
||||||
int start_col = iter->start.col;
|
struct range match;
|
||||||
|
bool found = find_next(
|
||||||
|
term, SEARCH_FORWARD,
|
||||||
|
grid_row_absolute_in_view(grid, iter->start.row),
|
||||||
|
iter->start.col,
|
||||||
|
term->rows - iter->start.row, &match);
|
||||||
|
|
||||||
for (int r = iter->start.row; r < term->rows; r++) {
|
if (found) {
|
||||||
const struct row *row = grid_row_in_view(term->grid, r);
|
LOG_DBG("match at %dx%d-%dx%d",
|
||||||
|
match.start.row, match.start.col,
|
||||||
|
match.end.row, match.end.col);
|
||||||
|
|
||||||
for (int c = start_col; c < term->cols; c++) {
|
/* Convert absolute row numbers back to view relative */
|
||||||
if (matches_cell(term, &row->cells[c], 0) < 0)
|
match.start.row = match.start.row - grid->view + grid->num_rows;
|
||||||
continue;
|
match.start.row &= grid->num_rows - 1;
|
||||||
|
match.end.row = match.end.row - grid->view + grid->num_rows;
|
||||||
|
match.end.row &= grid->num_rows - 1;
|
||||||
|
|
||||||
struct range match = {
|
/* Continue at next column, next time */
|
||||||
.start = {c, r},
|
iter->start.row = match.end.row;
|
||||||
.end = {-1, -1},
|
iter->start.col = match.end.col + 1;
|
||||||
};
|
return match;
|
||||||
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:
|
no_match:
|
||||||
iter->start.row = -1;
|
iter->start.row = -1;
|
||||||
iter->start.col = -1;
|
iter->start.col = -1;
|
||||||
return (struct range){{-1, -1}, {-1, -1}};
|
return (struct range){{-1, -1}, {-1, -1}};
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,7 @@ enum selection_kind {
|
||||||
};
|
};
|
||||||
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
||||||
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
||||||
|
enum search_direction { SEARCH_BACKWARD, SEARCH_FORWARD};
|
||||||
|
|
||||||
struct ptmx_buffer {
|
struct ptmx_buffer {
|
||||||
void *data;
|
void *data;
|
||||||
|
|
@ -501,7 +502,7 @@ struct terminal {
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
size_t cursor;
|
size_t cursor;
|
||||||
enum { SEARCH_BACKWARD, SEARCH_FORWARD} direction;
|
enum search_direction direction;
|
||||||
|
|
||||||
int original_view;
|
int original_view;
|
||||||
bool view_followed_offset;
|
bool view_followed_offset;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue