mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
commit
ed081f5f3c
5 changed files with 70 additions and 4 deletions
|
|
@ -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
3
csi.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
23
extract.c
23
extract.c
|
|
@ -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;
|
||||
|
|
|
|||
2
render.c
2
render.c
|
|
@ -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
44
vt.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue