Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/tsm/libtsm-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ struct tsm_screen {
};

void screen_cell_init(struct tsm_screen *con, struct cell *cell);
void screen_fill(struct tsm_screen *con, tsm_symbol_t ch,
const struct tsm_screen_attr *attr);

void tsm_screen_set_opts(struct tsm_screen *scr, unsigned int opts);
void tsm_screen_reset_opts(struct tsm_screen *scr, unsigned int opts);
Expand Down
29 changes: 29 additions & 0 deletions src/tsm/tsm-screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1604,3 +1604,32 @@ void tsm_screen_erase_screen(struct tsm_screen *con, bool protect)
screen_erase_region(con, 0, 0, con->size_x - 1, con->size_y - 1,
protect);
}

void screen_fill(struct tsm_screen *con, tsm_symbol_t ch,
const struct tsm_screen_attr *attr)
{
unsigned int len, x, y;
struct line *line;
struct cell cell;

if (!con)
return;

len = tsm_symbol_get_width(con->sym_table, ch);
if (len != 1)
return;

screen_inc_age(con);

cell.ch = ch;
cell.width = len;
memcpy(&cell.attr, attr, sizeof(cell.attr));
cell.age = con->age_cnt;

for (y = 0; y < con->size_y; ++y) {
line = con->lines[y];
for (x = 0; x < con->size_x; ++x) {
memcpy(&line->cells[x], &cell, sizeof(line->cells[x]));
}
}
}
16 changes: 16 additions & 0 deletions src/tsm/tsm-vte.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ enum parser_action {
#define CSI_PLUS 0x0100 /* CSI: + */
#define CSI_POPEN 0x0200 /* CSI: ( */
#define CSI_PCLOSE 0x0400 /* CSI: ) */
#define CSI_HASH 0x0800 /* CSI: # */

/* max CSI arguments */
#define CSI_ARG_MAX 16
Expand Down Expand Up @@ -918,6 +919,9 @@ static void do_collect(struct tsm_vte *vte, uint32_t data)
case ')':
vte->csi_flags |= CSI_PCLOSE;
break;
case '#':
vte->csi_flags |= CSI_HASH;
break;
}
}

Expand Down Expand Up @@ -1053,6 +1057,18 @@ static void do_esc(struct tsm_vte *vte, uint32_t data)
return;
}
break;
case '8':
if (vte->csi_flags & CSI_HASH) {
/* DECALN */
/* DEC Screen Alignment Test */
vte->flags &= ~FLAG_ORIGIN_MODE;
tsm_screen_reset_flags(vte->con, TSM_SCREEN_REL_ORIGIN);
screen_fill(vte->con, 'E', &vte->def_attr);
tsm_screen_move_to(vte->con, 0, 0);
tsm_screen_set_margins(vte->con, 1, vte->con->size_y);
return;
}
break;
}

/* everything below is only valid without CSI flags */
Expand Down
2 changes: 1 addition & 1 deletion test/test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static inline int test_run_suite(Suite *s)
SRunner *sr;

sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
srunner_run_all(sr, CK_ENV);
ret = srunner_ntests_failed(sr);
srunner_free(sr);

Expand Down
81 changes: 81 additions & 0 deletions test/test_vte.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,91 @@ TEST_DEFINE_CASE(misc)
TEST(test_vte_backspace_key)
TEST_END_CASE

START_TEST(test_vte_DECALN)
{
struct tsm_screen *screen;
struct tsm_vte *vte;
struct tsm_screen_attr attr;
const char *input;
unsigned int x, y, i;
tsm_age_t age;
int r;

r = tsm_screen_new(&screen, log_cb, NULL);
ck_assert_int_eq(r, 0);

tsm_screen_set_flags(screen, TSM_SCREEN_AUTO_WRAP);

i = 0;
for (y = 0; y < screen->size_y; ++y) {
for (x = 0; x < screen->size_x; ++x, ++i) {
attr.fr = i * 1;
attr.fg = i * 2;
attr.fb = i * 3;
attr.br = i * 4;
attr.bg = i * 5;
attr.bb = i * 6;
attr.bold = !!(i & 0x01);
attr.italic = !!(i & 0x02);
attr.underline = !!(i & 0x04);
attr.inverse = !!(i & 0x08);
attr.protect = !!(i & 0x10);
attr.blink = !!(i & 0x20);
tsm_screen_write(screen, '!' + (i % ('~' - '!')), &attr);
}
}

r = tsm_screen_set_margins(screen, 3, screen->size_y - 5);
ck_assert_int_eq(r, 0);

r = tsm_vte_new(&vte, screen, write_cb, NULL, log_cb, NULL);
ck_assert_int_eq(r, 0);

tsm_vte_get_def_attr(vte, &attr);
age = screen->age;

input = "\x1b[?6h" /* DECSET(DECOM) */ "\x1b#8" /* DECALN */;
tsm_vte_input(vte, input, strlen(input));

i = 0;
for (y = 0; y < screen->size_y; ++y) {
for (x = 0; x < screen->size_x; ++x, ++i) {
ck_assert_uint_eq(screen->lines[y]->cells[x].ch, 'E');
ck_assert_uint_eq(screen->lines[y]->cells[x].width, 1);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.fr, attr.fr);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.fg, attr.fg);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.fb, attr.fb);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.br, attr.br);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.bg, attr.bg);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.bb, attr.bb);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.bold, 0);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.italic, 0);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.underline, 0);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.inverse, 0);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.protect, 0);
ck_assert_uint_eq(screen->lines[y]->cells[x].attr.blink, 0);
ck_assert_uint_gt(screen->lines[y]->cells[x].age, age);
}
}

ck_assert_uint_ne(tsm_screen_get_flags(screen) & TSM_SCREEN_REL_ORIGIN, TSM_SCREEN_REL_ORIGIN);
ck_assert_uint_eq(tsm_screen_get_cursor_x(screen), 0);
ck_assert_uint_eq(tsm_screen_get_cursor_y(screen), 0);
ck_assert_uint_eq(screen->margin_top, 0);
ck_assert_uint_eq(screen->margin_bottom, screen->size_y - 1);
ck_assert_uint_lt(screen->cursor_x, screen->size_x);
}
END_TEST

TEST_DEFINE_CASE(control_sequences)
TEST(test_vte_DECALN)
TEST_END_CASE

// clang-format off
TEST_DEFINE(
TEST_SUITE(vte,
TEST_CASE(misc),
TEST_CASE(control_sequences),
TEST_END
)
)
Expand Down