Merge branch 'tabs'

Closes #508
This commit is contained in:
Daniel Eklöf 2021-06-09 09:58:29 +02:00
commit ed081f5f3c
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 70 additions and 4 deletions

View file

@ -101,6 +101,8 @@
* Reverse video (`\E[?5h`) now only swaps the default foreground and
background colors. Cells with explicit foreground and/or background
colors remain unchanged.
* Tabs (`\t`) are now preserved when the window is resized, and when
copying text (https://codeberg.org/dnkl/foot/issues/508).
### Deprecated

3
csi.c
View file

@ -1120,7 +1120,10 @@ csi_dispatch(struct terminal *term, uint8_t final)
}
}
xassert(new_col >= term->grid->cursor.point.col);
bool lcf = term->grid->cursor.lcf;
term_cursor_right(term, new_col - term->grid->cursor.point.col);
term->grid->cursor.lcf = lcf;
}
break;
}

View file

@ -9,6 +9,7 @@ struct extraction_context {
wchar_t *buf;
size_t size;
size_t idx;
size_t tab_spaces_left;
size_t empty_count;
size_t newline_count;
bool strip_trailing_empty;
@ -191,8 +192,17 @@ extract_one(const struct terminal *term, const struct row *row,
}
ctx->empty_count = 0;
}
ctx->tab_spaces_left = 0;
}
if (cell->wc == L' ' && ctx->tab_spaces_left > 0) {
ctx->tab_spaces_left--;
return true;
}
ctx->tab_spaces_left = 0;
if (cell->wc == 0) {
ctx->empty_count++;
ctx->last_row = row;
@ -231,6 +241,19 @@ extract_one(const struct terminal *term, const struct row *row,
if (!ensure_size(ctx, 1))
goto err;
ctx->buf[ctx->idx++] = cell->wc;
if (cell->wc == L'\t') {
int next_tab_stop = term->cols - 1;
tll_foreach(term->tab_stops, it) {
if (it->item > col) {
next_tab_stop = it->item;
break;
}
}
xassert(next_tab_stop >= col);
ctx->tab_spaces_left = next_tab_stop - col;
}
}
ctx->last_row = row;

View file

@ -620,7 +620,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->wc >= CELL_SPACER ||
if (cell->wc == 0 || cell->wc >= CELL_SPACER || cell->wc == L'\t' ||
(unlikely(cell->attrs.conceal) && !is_selected))
{
goto draw_cursor;

44
vt.c
View file

@ -162,20 +162,58 @@ action_execute(struct terminal *term, uint8_t c)
case '\t': {
/* HT - horizontal tab */
int start_col = term->grid->cursor.point.col;
int new_col = term->cols - 1;
tll_foreach(term->tab_stops, it) {
if (it->item > term->grid->cursor.point.col) {
if (it->item > start_col) {
new_col = it->item;
break;
}
}
xassert(new_col >= term->grid->cursor.point.col);
xassert(new_col >= start_col);
xassert(new_col < term->cols);
struct row *row = term->grid->cur_row;
bool emit_tab_char = (row->cells[start_col].wc == 0 ||
row->cells[start_col].wc == L' ');
/* Check if all cells from here until the next tab stop are empty */
for (const struct cell *cell = &row->cells[start_col + 1];
cell < &row->cells[new_col];
cell++)
{
if (!(cell->wc == 0 || cell->wc == L' ')) {
emit_tab_char = false;
break;
}
}
/*
* Emit a tab in current cell, and write spaces to the
* subsequent cells, all the way until the next tab stop.
*/
if (emit_tab_char) {
row->dirty = true;
row->cells[start_col].wc = '\t';
row->cells[start_col].attrs.clean = 0;
for (struct cell *cell = &row->cells[start_col + 1];
cell < &row->cells[new_col];
cell++)
{
cell->wc = L' ';
cell->attrs.clean = 0;
}
}
/* According to the specification, HT _should_ cancel LCF. But
* XTerm, and nearly all other emulators, don't. So we follow
* suit */
bool lcf = term->grid->cursor.lcf;
term_cursor_right(term, new_col - term->grid->cursor.point.col);
term_cursor_right(term, new_col - start_col);
term->grid->cursor.lcf = lcf;
break;
}