diff options
Diffstat (limited to 'tests/test_tui.c')
| -rw-r--r-- | tests/test_tui.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/tests/test_tui.c b/tests/test_tui.c index aa062fc..b48544e 100644 --- a/tests/test_tui.c +++ b/tests/test_tui.c @@ -153,6 +153,108 @@ static void test_field_fresh(void) fresh = 1; CHECK(tui_field_edit(buf, sizeof buf, &pos, KEY_DC, &fresh)); CHECK(strcmp(buf, "bc") == 0); + + /* after Backspace/Del/^U the next printable edits, it never replaces + the whole value (the "text disappears" bug) */ + snprintf(buf, sizeof buf, "Kontor"); + pos = (size_t)-1; + fresh = 1; + CHECK(tui_field_edit(buf, sizeof buf, &pos, KEY_BACKSPACE, &fresh)); + CHECK(fresh == 0); + CHECK(tui_field_edit(buf, sizeof buf, &pos, 'x', &fresh)); + CHECK(strcmp(buf, "Kontox") == 0); + snprintf(buf, sizeof buf, "abc"); + pos = 0; + fresh = 1; + tui_field_edit(buf, sizeof buf, &pos, KEY_DC, &fresh); + tui_field_edit(buf, sizeof buf, &pos, 'x', &fresh); + CHECK(strcmp(buf, "xbc") == 0); + snprintf(buf, sizeof buf, "abc"); + pos = (size_t)-1; + fresh = 1; + tui_field_edit(buf, sizeof buf, &pos, 21, &fresh); + tui_field_edit(buf, sizeof buf, &pos, 'x', &fresh); + tui_field_edit(buf, sizeof buf, &pos, 'y', &fresh); + CHECK(strcmp(buf, "xy") == 0); + /* a key the editor ignores keeps the field fresh */ + snprintf(buf, sizeof buf, "abc"); + pos = (size_t)-1; + fresh = 1; + CHECK(tui_field_edit(buf, sizeof buf, &pos, KEY_F(7), &fresh) == 0); + CHECK(fresh == 1); + /* a multi-byte first key replaces the value once, as one character */ + snprintf(buf, sizeof buf, "abc"); + pos = (size_t)-1; + fresh = 1; + tui_field_edit(buf, sizeof buf, &pos, 0xC3, &fresh); + tui_field_edit(buf, sizeof buf, &pos, 0xA5, &fresh); + CHECK(strcmp(buf, "å") == 0); +} + +static void test_ledit_utf8_full(void) +{ + char buf[4]; + struct tui_ledit e; + snprintf(buf, sizeof buf, "ab"); + tui_le_init(&e, buf, sizeof buf); + /* "å" needs two bytes, only one is free: the whole character is + dropped, including its continuation byte */ + tui_le_key(&e, 0xC3); + tui_le_key(&e, 0xA5); + CHECK(strcmp(buf, "ab") == 0 && e.len == 2); + tui_le_key(&e, 'c'); + CHECK(strcmp(buf, "abc") == 0); + /* a stray continuation byte is never inserted on its own */ + char b2[8] = ""; + tui_le_init(&e, b2, sizeof b2); + tui_le_key(&e, 0xA5); + CHECK(e.len == 0); + tui_le_key(&e, 0xC3); + tui_le_key(&e, 0xA5); + tui_le_key(&e, 0xA5); /* a third byte does not extend a 2-byte "å" */ + CHECK(strcmp(b2, "å") == 0); +} + +static void test_field_scroll(void) +{ + /* fits: no scroll */ + CHECK(tui_field_scroll("abc", 3, 10, 0) == 0); + /* caret at the end of a 10-char text in a 5-column field: 4 chars + before the caret, the caret in the last column */ + CHECK(tui_field_scroll("abcdefghij", 10, 5, 0) == 6); + /* moving the caret left inside the view keeps the scroll */ + CHECK(tui_field_scroll("abcdefghij", 8, 5, 6) == 6); + /* moving left past the view scrolls back to the caret */ + CHECK(tui_field_scroll("abcdefghij", 2, 5, 6) == 2); + /* Home */ + CHECK(tui_field_scroll("abcdefghij", 0, 5, 6) == 0); + /* deleted text: scroll back as far as the tail fits */ + CHECK(tui_field_scroll("abcdef", 6, 5, 4) == 2); + CHECK(tui_field_scroll("abc", 3, 5, 2) == 0); + /* multi-byte: offsets stay on character boundaries */ + const char *s = "åäöåäö"; /* 12 bytes, 6 columns */ + size_t st = tui_field_scroll(s, 12, 4, 0); + CHECK(st == 6 && tui_disp_width(s + st) == 3); + CHECK(tui_field_scroll(s, 12, 4, 7) == 6); /* mid-character start */ + /* a stale start past the end (another cell's text) resets */ + CHECK(tui_field_scroll("ab", 2, 5, 40) == 0); + CHECK(tui_field_scroll("", 0, 1, 0) == 0); +} + +static void test_form_scroll(void) +{ + /* everything fits */ + CHECK(tui_form_scroll(0, 3, 5, 10) == 0); + /* focus below the view scrolls down just enough */ + CHECK(tui_form_scroll(0, 12, 20, 10) == 3); + /* focus inside the view keeps the offset */ + CHECK(tui_form_scroll(3, 5, 20, 10) == 3); + /* focus above the view scrolls up to it */ + CHECK(tui_form_scroll(8, 2, 20, 10) == 2); + /* never scroll past the last line */ + CHECK(tui_form_scroll(15, 19, 20, 10) == 10); + /* a shrunken form clamps */ + CHECK(tui_form_scroll(9, 0, 3, 10) == 0); } static void date_feed(char *buf, size_t cap, const char *digits) @@ -202,6 +304,15 @@ static void test_date_field(void) fresh = 1; CHECK(tui_date_field_edit(buf, sizeof buf, &pos, 21, &fresh)); CHECK(strcmp(buf, "") == 0); + + /* after Backspace the next digit is inserted, not a fresh date */ + snprintf(buf, sizeof buf, "2026-03-15"); + pos = (size_t)-1; + fresh = 1; + tui_date_field_edit(buf, sizeof buf, &pos, KEY_BACKSPACE, &fresh); + CHECK(fresh == 0); + tui_date_field_edit(buf, sizeof buf, &pos, '9', &fresh); + CHECK(strcmp(buf, "2026-03-19") == 0); } static void nav_init(struct tui_list_nav *v, int n) @@ -635,6 +746,19 @@ static void test_rowtable(void) CHECK(t.nrows == 1); tui_rt_clear(&t); CHECK(t.nrows == 1); /* never below one row */ + + /* moving to another cell forgets the old caret and scroll: the next + ←/→ works from the end of the new cell */ + t.nrows = 3; + t.row = 0; + t.pos = 3; + t.hscroll = 5; + t.fresh = 0; + tui_rt_move(&t, 1, 0); + CHECK(t.pos == (size_t)-1 && t.hscroll == 0 && t.fresh == 1); + t.pos = 2; + tui_rt_tab(&t, 1); + CHECK(t.pos == (size_t)-1); } static void test_rt_fields(void) @@ -813,6 +937,9 @@ int main(void) test_parse_kr(); test_ledit(); test_field_fresh(); + test_ledit_utf8_full(); + test_field_scroll(); + test_form_scroll(); test_date_field(); test_styles(); test_markup(); |
