Files
roro9stack/lib/ui/src/text_wrap.cpp
T
twislaandClaude Opus 5.5 879cb0d0b6 Add widget kit, input layer with Compose Key, Launcher and demo apps
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
2026-10-02 10:35:48 +02:00

61 lines
1.9 KiB
C++

#include "text_wrap.h"
#include "utf8.h"
namespace roro {
namespace {
void wrapParagraph(const std::string& para, int maxWidth, const MeasureText& measure,
std::vector<std::string>& out) {
std::string line;
size_t pos = 0;
while (pos < para.size()) {
size_t space = para.find(' ', pos);
std::string word = para.substr(pos, space == std::string::npos ? std::string::npos : space - pos);
pos = space == std::string::npos ? para.size() : space + 1;
std::string candidate = line.empty() ? word : line + " " + word;
if (measure(candidate) <= maxWidth) {
line = candidate;
continue;
}
if (!line.empty()) {
out.push_back(line);
line.clear();
}
// The word alone may still be too wide: cut it character by character.
while (measure(word) > maxWidth) {
size_t cut = 0;
while (true) {
size_t nextCut = utf8::next(word, cut);
if (measure(word.substr(0, nextCut)) > maxWidth) break;
cut = nextCut;
}
if (cut == 0) cut = utf8::next(word, 0); // a single character wider than the line
out.push_back(word.substr(0, cut));
word = word.substr(cut);
}
line = word;
}
out.push_back(line);
}
} // namespace
std::vector<std::string> wrapText(const std::string& text, int maxWidth, const MeasureText& measure) {
std::vector<std::string> lines;
if (text.empty()) return lines;
size_t start = 0;
while (true) {
size_t nl = text.find('\n', start);
wrapParagraph(text.substr(start, nl == std::string::npos ? std::string::npos : nl - start), maxWidth,
measure, lines);
if (nl == std::string::npos) break;
start = nl + 1;
}
return lines;
}
} // namespace roro