mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Merge branch 'multi-column-special-spacer-value'
This commit is contained in:
commit
6b0b3ddccc
6 changed files with 69 additions and 55 deletions
27
grid.c
27
grid.c
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
8
render.c
8
render.c
|
|
@ -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);
|
||||
|
|
|
|||
30
selection.c
30
selection.c
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
41
terminal.c
41
terminal.c
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
12
vt.c
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue