From 4cf7195695e2112031c630ff1102beb0f7f57e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 14 Jul 2020 13:17:50 +0200 Subject: [PATCH] selection: recognize empty padding cells in a forced linewrap When printing a multi-column character at the end of the line, and it doesn't fit, we currently insert a forced line-wrap. This means the last character(s) on the previous line will be empty, followed by a multi-column character in the first cell on the next line. Without special code to handle this, the selection text extraction code will insert a hard newline, since this is normally the correct thing to do. Add a TODO, to consider writing a special place holder value to these padding cells. --- selection.c | 44 +++++++++++++++++++++++++++++++++++--------- terminal.c | 10 ++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/selection.c b/selection.c index 3abe934c..cd3780a7 100644 --- a/selection.c +++ b/selection.c @@ -269,15 +269,41 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell, { struct extract *ctx = data; - if (ctx->last_row != NULL && row != ctx->last_row && - ((term->selection.kind == SELECTION_NORMAL && - (ctx->last_row->linebreak || - ctx->empty_count > 0 || cell->wc == 0)) || - term->selection.kind == SELECTION_BLOCK)) - { - /* Last cell was the last column in the selection */ - ctx->buf[ctx->idx++] = L'\n'; - ctx->empty_count = 0; + if (ctx->last_row != NULL && row != ctx->last_row) { + /* New row - determine if we should insert a newline or not */ + + if (term->selection.kind == SELECTION_NORMAL) { + int width = max(1, wcwidth(cell->wc)); + + if (width > 1) { + /* Heuristict to handle force-wrapped multi-column + * characters */ + + /* + * TODO: maybe we should print a placeholder value to + * the empty cells at the end of the line when + * force-wrapping? Then extract() could simply skip + * those cells + */ + ctx->empty_count -= min(width, ctx->empty_count); + } + + else if (ctx->last_row->linebreak || + ctx->empty_count > 0 || + cell->wc == 0) + { + /* Row has a hard linebreak, or either last cell or + * current cell is empty */ + ctx->buf[ctx->idx++] = L'\n'; + ctx->empty_count = 0; + } + } + + else if (term->selection.kind == SELECTION_BLOCK) { + /* Always insert a linebreak */ + ctx->buf[ctx->idx++] = L'\n'; + ctx->empty_count = 0; + } } if (cell->wc == 0) { diff --git a/terminal.c b/terminal.c index 150d5335..eda311da 100644 --- a/terminal.c +++ b/terminal.c @@ -2399,6 +2399,16 @@ term_print(struct terminal *term, wchar_t wc, int width) /* Multi-column character that doesn't fit on current line - * force a line wrap */ term->grid->cursor.lcf = 1; + + /* + * TODO: should we insert place holder values in the remaining + * cells? This would allow e.g. text extraction to simply + * skip these, instead of trying to recognize a sequence of + * empty cells at the end of the line followed by a + * multi-column character... + * + * Might also make text reflow easier, or even more correct. + */ } print_linewrap(term);