diff --git a/input.c b/input.c index 0b45c5ad..d046bb4a 100644 --- a/input.c +++ b/input.c @@ -276,7 +276,7 @@ execute_binding(struct seat *seat, struct terminal *term, if (selection_enabled(term, seat) && cursor_is_on_grid) { selection_start( term, seat->mouse.col, seat->mouse.row, - SELECTION_NORMAL, SELECTION_SEMANTIC_NONE); + SELECTION_NORMAL, SELECTION_SEMANTIC_NONE, false); return true; } return false; @@ -285,7 +285,7 @@ execute_binding(struct seat *seat, struct terminal *term, if (selection_enabled(term, seat) && cursor_is_on_grid) { selection_start( term, seat->mouse.col, seat->mouse.row, - SELECTION_BLOCK, SELECTION_SEMANTIC_NONE); + SELECTION_BLOCK, SELECTION_SEMANTIC_NONE, false); return true; } return false; @@ -300,23 +300,26 @@ execute_binding(struct seat *seat, struct terminal *term, case BIND_ACTION_SELECT_WORD: if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_mark_word( - seat, term, seat->mouse.col, seat->mouse.row, false, serial); + selection_start( + term, seat->mouse.col, seat->mouse.row, + SELECTION_NORMAL, SELECTION_SEMANTIC_WORD, false); return true; } return false; case BIND_ACTION_SELECT_WORD_WS: if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_mark_word( - seat, term, seat->mouse.col, seat->mouse.row, true, serial); + selection_start( + term, seat->mouse.col, seat->mouse.row, + SELECTION_NORMAL, SELECTION_SEMANTIC_WORD, true); return true; } return false; case BIND_ACTION_SELECT_ROW: if (selection_enabled(term, seat) && cursor_is_on_grid) { - selection_mark_row(seat, term, seat->mouse.row, serial); + selection_start(term, seat->mouse.col, seat->mouse.row, + SELECTION_NORMAL, SELECTION_SEMANTIC_ROW, false); return true; } return false; diff --git a/search.c b/search.c index 034fc7c9..c4fd8f05 100644 --- a/search.c +++ b/search.c @@ -223,7 +223,7 @@ 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_SEMANTIC_NONE); + SELECTION_NORMAL, SELECTION_SEMANTIC_NONE, false); } /* Update selection endpoint */ diff --git a/selection.c b/selection.c index c4eeba02..4b7baf13 100644 --- a/selection.c +++ b/selection.c @@ -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) { diff --git a/selection.h b/selection.h index db83ef83..21e983e8 100644 --- a/selection.h +++ b/selection.h @@ -11,7 +11,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, enum selection_semantic semantic); + enum selection_kind kind, enum selection_semantic semantic, + bool spaces_only); void selection_update(struct terminal *term, int col, int row); void selection_finalize( struct seat *seat, struct terminal *term, uint32_t serial); @@ -25,12 +26,6 @@ bool selection_on_rows(const struct terminal *term, int start, int end); void selection_view_up(struct terminal *term, int new_view); void selection_view_down(struct terminal *term, int new_view); -void selection_mark_word( - struct seat *seat, struct terminal *term, int col, int row, - bool spaces_only, uint32_t serial); -void selection_mark_row( - struct seat *seat, struct terminal *term, int row, uint32_t serial); - void selection_clipboard_unset(struct seat *seat); void selection_primary_unset(struct seat *seat);