mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
selection: wip: update selection word-wise when initial selection was by word
This commit is contained in:
parent
482690e5fb
commit
30de262d29
5 changed files with 95 additions and 58 deletions
6
input.c
6
input.c
|
|
@ -275,7 +275,8 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
case BIND_ACTION_SELECT_BEGIN:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row, SELECTION_NORMAL);
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_NONE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -283,7 +284,8 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
case BIND_ACTION_SELECT_BEGIN_BLOCK:
|
||||
if (selection_enabled(term, seat) && cursor_is_on_grid) {
|
||||
selection_start(
|
||||
term, seat->mouse.col, seat->mouse.row, SELECTION_BLOCK);
|
||||
term, seat->mouse.col, seat->mouse.row,
|
||||
SELECTION_BLOCK, SELECTION_SEMANTIC_NONE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
3
search.c
3
search.c
|
|
@ -222,7 +222,8 @@ search_update_selection(struct terminal *term,
|
|||
|
||||
assert(selection_row >= 0 &&
|
||||
selection_row < term->grid->num_rows);
|
||||
selection_start(term, start_col, selection_row, SELECTION_NORMAL);
|
||||
selection_start(term, start_col, selection_row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_NONE);
|
||||
}
|
||||
|
||||
/* Update selection endpoint */
|
||||
|
|
|
|||
139
selection.c
139
selection.c
|
|
@ -238,7 +238,7 @@ selection_to_text(const struct terminal *term)
|
|||
|
||||
void
|
||||
selection_start(struct terminal *term, int col, int row,
|
||||
enum selection_kind kind)
|
||||
enum selection_kind kind, enum selection_semantic semantic)
|
||||
{
|
||||
selection_cancel(term);
|
||||
|
||||
|
|
@ -248,6 +248,7 @@ selection_start(struct terminal *term, int col, int row,
|
|||
row, col);
|
||||
|
||||
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;
|
||||
|
|
@ -360,6 +361,68 @@ 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)
|
||||
{
|
||||
|
|
@ -434,6 +497,22 @@ selection_update(struct terminal *term, int col, int row)
|
|||
}
|
||||
}
|
||||
|
||||
if (term->selection.semantic == SELECTION_SEMANTIC_WORD) {
|
||||
switch (term->selection.direction) {
|
||||
case SELECTION_LEFT:
|
||||
find_word_boundary_left(term, &new_end, false);
|
||||
break;
|
||||
|
||||
case SELECTION_RIGHT:
|
||||
find_word_boundary_right(term, &new_end, false);
|
||||
break;
|
||||
|
||||
case SELECTION_UNDIR:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If an end point is in the middle of a multi-column character,
|
||||
* expand the selection to cover the entire character */
|
||||
if (new_start.row < new_end.row ||
|
||||
|
|
@ -742,59 +821,11 @@ selection_mark_word(struct seat *seat, struct terminal *term, int col, int row,
|
|||
struct coord start = {col, row};
|
||||
struct coord end = {col, row};
|
||||
|
||||
const struct row *r = grid_row_in_view(term->grid, start.row);
|
||||
wchar_t c = r->cells[start.col].wc;
|
||||
find_word_boundary_left(term, &start, spaces_only);
|
||||
find_word_boundary_right(term, &end, spaces_only);
|
||||
|
||||
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
|
||||
while (true) {
|
||||
int next_col = start.col - 1;
|
||||
int next_row = start.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;
|
||||
|
||||
start.col = next_col;
|
||||
start.row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
r = grid_row_in_view(term->grid, end.row);
|
||||
c = r->cells[end.col].wc;
|
||||
|
||||
if (!(c == 0 || !isword(c, spaces_only, term->conf->word_delimiters))) {
|
||||
while (true) {
|
||||
int next_col = end.col + 1;
|
||||
int next_row = end.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;
|
||||
|
||||
end.col = next_col;
|
||||
end.row = next_row;
|
||||
}
|
||||
}
|
||||
|
||||
selection_start(term, start.col, start.row, SELECTION_NORMAL);
|
||||
selection_start(term, start.col, start.row,
|
||||
SELECTION_NORMAL, SELECTION_SEMANTIC_WORD);
|
||||
selection_update(term, end.col, end.row);
|
||||
selection_finalize(seat, term, serial);
|
||||
}
|
||||
|
|
@ -803,7 +834,7 @@ void
|
|||
selection_mark_row(
|
||||
struct seat *seat, struct terminal *term, int row, uint32_t serial)
|
||||
{
|
||||
selection_start(term, 0, row, SELECTION_NORMAL);
|
||||
selection_start(term, 0, row, SELECTION_NORMAL, SELECTION_SEMANTIC_NONE);
|
||||
selection_update(term, term->cols - 1, row);
|
||||
selection_finalize(seat, term, serial);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ extern const struct zwp_primary_selection_device_v1_listener primary_selection_d
|
|||
|
||||
bool selection_enabled(const struct terminal *term, struct seat *seat);
|
||||
void selection_start(
|
||||
struct terminal *term, int col, int row, enum selection_kind kind);
|
||||
struct terminal *term, int col, int row,
|
||||
enum selection_kind kind, enum selection_semantic semantic);
|
||||
void selection_update(struct terminal *term, int col, int row);
|
||||
void selection_finalize(
|
||||
struct seat *seat, struct terminal *term, uint32_t serial);
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ enum mouse_reporting {
|
|||
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
||||
|
||||
enum selection_kind { SELECTION_NONE, SELECTION_NORMAL, SELECTION_BLOCK };
|
||||
enum selection_semantic { SELECTION_SEMANTIC_NONE, SELECTION_SEMANTIC_WORD};
|
||||
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
||||
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
||||
|
||||
|
|
@ -359,6 +360,7 @@ struct terminal {
|
|||
|
||||
struct {
|
||||
enum selection_kind kind;
|
||||
enum selection_semantic semantic;
|
||||
enum selection_direction direction;
|
||||
struct coord start;
|
||||
struct coord end;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue