selection: use selection_start() to initialize word/row-based selection

This removes the selection_mark_word() and selection_mark_row()
functions. To start a word/row-based selection, use selection_start()
with SELECTION_SEMANTIC_{WORD,ROW}
This commit is contained in:
Daniel Eklöf 2021-01-02 23:00:54 +01:00
parent 3dd6b7e4ef
commit 3afc5a723e
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
4 changed files with 104 additions and 107 deletions

View file

@ -236,9 +236,73 @@ selection_to_text(const struct terminal *term)
return extract_finish(ctx, &text, NULL) ? text : NULL;
}
static void
find_word_boundary_left(struct terminal *term, struct coord *pos,
bool spaces_only)
{
const struct row *r = grid_row_in_view(term->grid, pos->row);
wchar_t c = r->cells[pos->col].wc;
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
while (true) {
int next_col = pos->col - 1;
int next_row = pos->row;
/* Linewrap */
if (next_col < 0) {
next_col = term->cols - 1;
if (--next_row < 0)
break;
}
const struct row *row = grid_row_in_view(term->grid, next_row);
c = row->cells[next_col].wc;
if (c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))
break;
pos->col = next_col;
pos->row = next_row;
}
}
}
static void
find_word_boundary_right(struct terminal *term, struct coord *pos,
bool spaces_only)
{
const struct row *r = grid_row_in_view(term->grid, pos->row);
wchar_t c = r->cells[pos->col].wc;
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
while (true) {
int next_col = pos->col + 1;
int next_row = pos->row;
/* Linewrap */
if (next_col >= term->cols) {
next_col = 0;
if (++next_row >= term->rows)
break;
}
const struct row *row = grid_row_in_view(term->grid, next_row);
c = row->cells[next_col].wc;
if (c == '\0' || !isword(c, spaces_only, term->conf->word_delimiters))
break;
pos->col = next_col;
pos->row = next_row;
}
}
}
void
selection_start(struct terminal *term, int col, int row,
enum selection_kind kind, enum selection_semantic semantic)
enum selection_kind kind,
enum selection_semantic semantic,
bool spaces_only)
{
selection_cancel(term);
@ -249,9 +313,33 @@ selection_start(struct terminal *term, int col, int row,
term->selection.kind = kind;
term->selection.semantic = semantic;
term->selection.start = (struct coord){col, term->grid->view + row};
term->selection.end = (struct coord){-1, -1};
term->selection.ongoing = true;
term->selection.spaces_only = spaces_only;
switch (semantic) {
case SELECTION_SEMANTIC_NONE:
term->selection.start = (struct coord){col, term->grid->view + row};
term->selection.end = (struct coord){-1, -1};
break;
case SELECTION_SEMANTIC_WORD: {
struct coord start = {col, row}, end = {col, row};
find_word_boundary_left(term, &start, spaces_only);
find_word_boundary_right(term, &end, spaces_only);
term->selection.start = (struct coord){
start.col, term->grid->view + start.row};
selection_update(term, end.col, end.row);
break;
}
case SELECTION_SEMANTIC_ROW:
term->selection.start = (struct coord){0, term->grid->view + row};
selection_update(term, term->cols - 1, row);
break;
}
}
/* Context used while (un)marking selected cells, to be able to
@ -361,68 +449,6 @@ selection_modify(struct terminal *term, struct coord start, struct coord end)
render_refresh(term);
}
static void
find_word_boundary_left(struct terminal *term, struct coord *pos,
bool spaces_only)
{
const struct row *r = grid_row_in_view(term->grid, pos->row);
wchar_t c = r->cells[pos->col].wc;
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
while (true) {
int next_col = pos->col - 1;
int next_row = pos->row;
/* Linewrap */
if (next_col < 0) {
next_col = term->cols - 1;
if (--next_row < 0)
break;
}
const struct row *row = grid_row_in_view(term->grid, next_row);
c = row->cells[next_col].wc;
if (c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))
break;
pos->col = next_col;
pos->row = next_row;
}
}
}
static void
find_word_boundary_right(struct terminal *term, struct coord *pos,
bool spaces_only)
{
const struct row *r = grid_row_in_view(term->grid, pos->row);
wchar_t c = r->cells[pos->col].wc;
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
while (true) {
int next_col = pos->col + 1;
int next_row = pos->row;
/* Linewrap */
if (next_col >= term->cols) {
next_col = 0;
if (++next_row >= term->rows)
break;
}
const struct row *row = grid_row_in_view(term->grid, next_row);
c = row->cells[next_col].wc;
if (c == '\0' || !isword(c, spaces_only, term->conf->word_delimiters))
break;
pos->col = next_col;
pos->row = next_row;
}
}
}
void
selection_update(struct terminal *term, int col, int row)
{
@ -833,33 +859,6 @@ selection_primary_unset(struct seat *seat)
primary->text = NULL;
}
void
selection_mark_word(struct seat *seat, struct terminal *term, int col, int row,
bool spaces_only, uint32_t serial)
{
selection_cancel(term);
struct coord start = {col, row};
struct coord end = {col, row};
find_word_boundary_left(term, &start, spaces_only);
find_word_boundary_right(term, &end, spaces_only);
selection_start(term, start.col, start.row,
SELECTION_NORMAL, SELECTION_SEMANTIC_WORD);
term->selection.spaces_only = spaces_only;
selection_update(term, end.col, end.row);
}
void
selection_mark_row(
struct seat *seat, struct terminal *term, int row, uint32_t serial)
{
selection_start(term, 0, row, SELECTION_NORMAL, SELECTION_SEMANTIC_ROW);
selection_update(term, term->cols - 1, row);
}
static bool
fdm_scroll_timer(struct fdm *fdm, int fd, int events, void *data)
{