From 056fd4ffe0d6f031638940383721f62318b6e631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 2 Jun 2020 18:21:39 +0200 Subject: [PATCH] selection: don't allow only half of double-width characters to be selected --- CHANGELOG.md | 2 ++ selection.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 094bcf6e..eb69307b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,8 @@ * Selection handling when viewport wrapped around. * Restore signal mask in the slave process. * Set `IUTF8`. +* Selection of double-width characters. It is no longer possible to + select half of a double-width character. ### Security diff --git a/selection.c b/selection.c index 0dce4484..44b23860 100644 --- a/selection.c +++ b/selection.c @@ -355,6 +355,7 @@ selection_start(struct terminal *term, int col, int row, kind == SELECTION_NORMAL ? "normal" : kind == SELECTION_BLOCK ? "block" : "", row, col); + term->selection.kind = kind; term->selection.start = (struct coord){col, term->grid->view + row}; term->selection.end = (struct coord){-1, -1}; @@ -434,8 +435,34 @@ selection_update(struct terminal *term, int col, int row) assert(term->grid->view + row != -1); + struct coord new_start = term->selection.start; struct coord new_end = {col, term->grid->view + row}; - selection_modify(term, term->selection.start, new_end); + + size_t start_row_idx = new_start.row & (term->grid->num_rows - 1); + size_t end_row_idx = new_end.row & (term->grid->num_rows - 1); + const struct row *row_start = term->grid->rows[start_row_idx]; + const struct row *row_end = term->grid->rows[end_row_idx]; + + /* Handle double-width characters */ + if (new_start.row < new_end.row || + (new_start.row == new_end.row && new_start.col <= new_end.col)) + { + if (new_start.col - 1 >= 0) + if (wcwidth(row_start->cells[new_start.col - 1].wc) > 1) + new_start.col--; + if (new_end.col + 1 < term->cols) + if (wcwidth(row_end->cells[new_end.col].wc) > 1) + new_end.col++; + } else { + if (new_end.col - 1 >= 0) + if (wcwidth(row_end->cells[new_end.col - 1].wc) > 1) + new_end.col--; + if (new_start.col + 1 < term->cols) + if (wcwidth(row_end->cells[new_start.col].wc) > 1) + new_start.col++; + } + + selection_modify(term, new_start, new_end); } void