Public Access
Steps 5 and 6 of M0. - lib/ui (host-tested): ListModel, LineEditor (UTF-8, byte-limited), wrapText, ToastQueue, DialogModel - lib/input (host-tested): KeyMapper turns keyboard state into logical keys (Fn arrows, ` Back, Fn+` Home) and composes accents with opt - src/ui: off-screen 16-bit frame pushed in one transfer (fixes the flicker), Status Bar, list, text, line editor, dialog, Toast widgets, Notifier (Toast + beep + LED), vendored public-domain Latin-1 fonts - Apps: minimal Launcher, Widget demo, Diagnostics (SD erase now behind a confirmation dialog) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
66 lines
2.0 KiB
C++
66 lines
2.0 KiB
C++
#include <unity.h>
|
|
|
|
#include "text_wrap.h"
|
|
|
|
using namespace roro;
|
|
|
|
void setUp() {}
|
|
void tearDown() {}
|
|
|
|
// Every character (code point) is 6 px wide.
|
|
static int measure(const std::string& s) {
|
|
int n = 0;
|
|
for (unsigned char c : s)
|
|
if ((c & 0xC0) != 0x80) n++;
|
|
return n * 6;
|
|
}
|
|
|
|
void test_short_text_is_one_line() {
|
|
auto lines = wrapText("hello", 60, measure);
|
|
TEST_ASSERT_EQUAL(1, lines.size());
|
|
TEST_ASSERT_EQUAL_STRING("hello", lines[0].c_str());
|
|
}
|
|
|
|
void test_wraps_at_word_boundaries() {
|
|
auto lines = wrapText("hello big world", 60, measure); // 10 chars per line
|
|
TEST_ASSERT_EQUAL(2, lines.size());
|
|
TEST_ASSERT_EQUAL_STRING("hello big", lines[0].c_str());
|
|
TEST_ASSERT_EQUAL_STRING("world", lines[1].c_str());
|
|
}
|
|
|
|
void test_breaks_words_longer_than_a_line() {
|
|
auto lines = wrapText("abcdefghijklmnop", 60, measure);
|
|
TEST_ASSERT_EQUAL(2, lines.size());
|
|
TEST_ASSERT_EQUAL_STRING("abcdefghij", lines[0].c_str());
|
|
TEST_ASSERT_EQUAL_STRING("klmnop", lines[1].c_str());
|
|
}
|
|
|
|
void test_never_splits_a_multibyte_character() {
|
|
// 12 x 'é' (2 bytes each) at 10 chars per line
|
|
std::string s;
|
|
for (int i = 0; i < 12; i++) s += "\xC3\xA9";
|
|
auto lines = wrapText(s, 60, measure);
|
|
TEST_ASSERT_EQUAL(2, lines.size());
|
|
TEST_ASSERT_EQUAL(20, lines[0].size());
|
|
TEST_ASSERT_EQUAL(4, lines[1].size());
|
|
}
|
|
|
|
void test_explicit_newlines_start_new_lines_and_keep_empty_ones() {
|
|
auto lines = wrapText("a\n\nb", 60, measure);
|
|
TEST_ASSERT_EQUAL(3, lines.size());
|
|
TEST_ASSERT_EQUAL_STRING("", lines[1].c_str());
|
|
}
|
|
|
|
void test_empty_text_is_no_lines() { TEST_ASSERT_EQUAL(0, wrapText("", 60, measure).size()); }
|
|
|
|
int main() {
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_short_text_is_one_line);
|
|
RUN_TEST(test_wraps_at_word_boundaries);
|
|
RUN_TEST(test_breaks_words_longer_than_a_line);
|
|
RUN_TEST(test_never_splits_a_multibyte_character);
|
|
RUN_TEST(test_explicit_newlines_start_new_lines_and_keep_empty_ones);
|
|
RUN_TEST(test_empty_text_is_no_lines);
|
|
return UNITY_END();
|
|
}
|