Merge branch 'multi-column-special-spacer-value'

This commit is contained in:
Daniel Eklöf 2020-07-15 08:20:10 +02:00
commit 6b0b3ddccc
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 69 additions and 55 deletions

27
grid.c
View file

@ -183,6 +183,13 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
} \
} while(0)
#define print_spacer() \
do { \
new_row->cells[new_col_idx].wc = CELL_MULT_COL_SPACER; \
new_row->cells[new_col_idx].attrs = old_cell->attrs; \
new_row->cells[new_col_idx].attrs.clean = 1; \
} while (0)
/*
* Keep track of empty cells. If the old line ends with a
* string of empty cells, we don't need to, nor do we want to,
@ -222,12 +229,19 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
/* Multi-column characters are never cut in half */
assert(c + width <= old_cols);
for (int i = 0; i < empty_count + width; i++) {
for (int i = 0; i < empty_count + 1; i++) {
const struct cell *old_cell = &old_row->cells[c - empty_count + i];
if (old_cell->wc == CELL_MULT_COL_SPACER)
continue;
/* Out of columns on current row in new grid? */
if (new_col_idx + max(1, wcwidth(old_cell->wc)) > new_cols)
if (new_col_idx + max(1, wcwidth(old_cell->wc)) > new_cols) {
/* Pad to end-of-line with spacers, then line-wrap */
for (;new_col_idx < new_cols; new_col_idx++)
print_spacer();
line_wrap();
}
assert(new_row != NULL);
assert(new_col_idx >= 0);
@ -247,6 +261,14 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
}
}
new_col_idx++;
/* For multi-column characters, insert spacers in the
* subsequent cells */
for (size_t i = 0; i < width - 1; i++) {
assert(new_col_idx < new_cols);
print_spacer();
new_col_idx++;
}
}
c += width - 1;
@ -258,6 +280,7 @@ grid_reflow(struct grid *grid, int new_rows, int new_cols,
line_wrap();
}
#undef print_spacer
#undef line_wrap
}

View file

@ -408,10 +408,10 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (cell->wc != 0) {
wchar_t base = cell->wc;
if (base >= COMB_CHARS_LO &&
base < (COMB_CHARS_LO + term->composed_count))
if (base >= CELL_COMB_CHARS_LO &&
base < (CELL_COMB_CHARS_LO + term->composed_count))
{
composed = &term->composed[base - COMB_CHARS_LO];
composed = &term->composed[base - CELL_COMB_CHARS_LO];
base = composed->base;
}
@ -438,7 +438,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (has_cursor && term->cursor_style == CURSOR_BLOCK && term->kbd_focus)
draw_cursor(term, cell, font, pix, &fg, &bg, x, y, cell_cols);
if (cell->wc == 0 || cell->attrs.conceal)
if (cell->wc == 0 || cell->wc == CELL_MULT_COL_SPACER || cell->attrs.conceal)
goto draw_cursor;
pixman_image_t *clr_pix = pixman_image_create_solid_fill(&fg);

View file

@ -134,9 +134,9 @@ foreach_selected_normal(
c <= (r == end_row ? end_col : term->cols - 1);
c++)
{
if (row->cells[c].wc == CELL_MULT_COL_SPACER)
continue;
cb(term, row, &row->cells[c], c, data);
c += max(1, wcwidth(row->cells[c].wc)) - 1;
assert(c < term->cols);
}
start_col = 0;
@ -168,9 +168,9 @@ foreach_selected_block(
assert(row != NULL);
for (int c = top_left.col; c <= bottom_right.col; c++) {
if (row->cells[c].wc == CELL_MULT_COL_SPACER)
continue;
cb(term, row, &row->cells[c], c, data);
c += max(1, wcwidth(row->cells[c].wc)) - 1;
assert(c < term->cols);
}
}
}
@ -273,22 +273,7 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell,
/* 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 ||
if (ctx->last_row->linebreak ||
ctx->empty_count > 0 ||
cell->wc == 0)
{
@ -321,8 +306,9 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell,
assert(ctx->idx + 1 <= ctx->size);
if (cell->wc >= COMB_CHARS_LO && cell->wc < (COMB_CHARS_LO + term->composed_count)) {
const struct composed *composed = &term->composed[cell->wc - COMB_CHARS_LO];
if (cell->wc >= CELL_COMB_CHARS_LO &&
cell->wc < (CELL_COMB_CHARS_LO + term->composed_count)) {
const struct composed *composed = &term->composed[cell->wc - CELL_COMB_CHARS_LO];
ctx->buf[ctx->idx++] = composed->base;

View file

@ -2387,33 +2387,39 @@ print_insert(struct terminal *term, int width)
row->cells[i].attrs.clean = 0;
}
static void
print_spacer(struct terminal *term, int col)
{
struct row *row = term->grid->cur_row;
struct cell *cell = &row->cells[col];
cell->wc = CELL_MULT_COL_SPACER;
cell->attrs = term->vt.attrs;
cell->attrs.clean = 0;
}
void
term_print(struct terminal *term, wchar_t wc, int width)
{
if (unlikely(width <= 0))
return;
if (unlikely(width > 1) &&
print_linewrap(term);
print_insert(term, width);
if (unlikely(width > 1) && likely(term->auto_margin) &&
term->grid->cursor.point.col + width > term->cols)
{
/* Multi-column character that doesn't fit on current line -
* force a line wrap */
* pad with spacers */
for (size_t i = term->grid->cursor.point.col; i < term->cols; i++)
print_spacer(term, i);
/* And 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);
}
print_linewrap(term);
print_insert(term, width);
sixel_overwrite_at_cursor(term, width);
/* *Must* get current cell *after* linewrap+insert */
@ -2429,10 +2435,7 @@ term_print(struct terminal *term, wchar_t wc, int width)
/* Advance cursor the 'additional' columns while dirty:ing the cells */
for (int i = 1; i < width && term->grid->cursor.point.col < term->cols - 1; i++) {
term->grid->cursor.point.col++;
struct cell *cell = &row->cells[term->grid->cursor.point.col];
cell->wc = 0;
cell->attrs.clean = 0;
print_spacer(term, term->grid->cursor.point.col);
}
/* Advance cursor */

View file

@ -48,6 +48,10 @@ struct attributes {
};
static_assert(sizeof(struct attributes) == 8, "bad size");
#define CELL_COMB_CHARS_LO 0x40000000ul
#define CELL_COMB_CHARS_HI 0x400ffffful
#define CELL_MULT_COL_SPACER 0x40100000ul
struct cell {
wchar_t wc;
struct attributes attrs;
@ -216,8 +220,6 @@ struct terminal {
struct grid alt;
struct grid *grid;
#define COMB_CHARS_LO 0x40000000ul
#define COMB_CHARS_HI 0x400ffffful
size_t composed_count;
struct composed *composed;

12
vt.c
View file

@ -550,9 +550,9 @@ action_utf8_print(struct terminal *term, wchar_t wc)
}
const struct composed *composed =
(base >= COMB_CHARS_LO &&
base < (COMB_CHARS_LO + term->composed_count))
? &term->composed[base - COMB_CHARS_LO]
(base >= CELL_COMB_CHARS_LO &&
base < (CELL_COMB_CHARS_LO + term->composed_count))
? &term->composed[base - CELL_COMB_CHARS_LO]
: NULL;
if (composed != NULL)
@ -635,7 +635,7 @@ action_utf8_print(struct terminal *term, wchar_t wc)
if (cc->combining[wanted_count - 1] != wc)
continue;
term_print(term, COMB_CHARS_LO + i, base_width);
term_print(term, CELL_COMB_CHARS_LO + i, base_width);
return;
}
@ -648,12 +648,12 @@ action_utf8_print(struct terminal *term, wchar_t wc)
new_cc.combining[i] = composed->combining[i];
new_cc.combining[wanted_count - 1] = wc;
if (term->composed_count < COMB_CHARS_HI) {
if (term->composed_count < CELL_COMB_CHARS_HI) {
term->composed_count++;
term->composed = realloc(term->composed, term->composed_count * sizeof(term->composed[0]));
term->composed[term->composed_count - 1] = new_cc;
term_print(term, COMB_CHARS_LO + term->composed_count - 1, base_width);
term_print(term, CELL_COMB_CHARS_LO + term->composed_count - 1, base_width);
return;
} else {
/* We reached our maximum number of allowed composed