From 30de262d29d703b0cc31799a4abf84239f3caf22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 2 Jan 2021 21:20:41 +0100 Subject: [PATCH] selection: wip: update selection word-wise when initial selection was by word --- input.c | 6 ++- search.c | 3 +- selection.c | 139 ++++++++++++++++++++++++++++++++-------------------- selection.h | 3 +- terminal.h | 2 + 5 files changed, 95 insertions(+), 58 deletions(-) diff --git a/input.c b/input.c index e4a1f306..0b45c5ad 100644 --- a/input.c +++ b/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; diff --git a/search.c b/search.c index a7b6f112..034fc7c9 100644 --- a/search.c +++ b/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 */ diff --git a/selection.c b/selection.c index db5a0b9f..3653fa1b 100644 --- a/selection.c +++ b/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); } diff --git a/selection.h b/selection.h index 1b74efb5..db83ef83 100644 --- a/selection.h +++ b/selection.h @@ -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); diff --git a/terminal.h b/terminal.h index 0774aaa1..8d032d20 100644 --- a/terminal.h +++ b/terminal.h @@ -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;