Skip to content

Commit ee14e29

Browse files
committed
Rewrite wrapMessage
1 parent ba87261 commit ee14e29

File tree

2 files changed

+96
-63
lines changed

2 files changed

+96
-63
lines changed

image_view.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ struct InteractiveTextOverlay {
3535

3636
void generatePreview() {
3737
preview.clear();
38-
for (auto [name, text]: messages) {
39-
auto wrapped = wrapMessage(name, params.usernameSeparator, text, params.maxCharsPerLine);
38+
for (const auto &[name, text]: messages) {
39+
auto [username, wrapped] = wrapMessage(name, params.usernameSeparator, text, params.maxCharsPerLine);
4040
if (wrapped.empty()) {
4141
continue;
4242
}
4343
if (preview.size() < params.totalDisplayLines) {
44-
preview.emplace_back(name, wrapped[0]);
44+
preview.emplace_back(username, wrapped[0]);
4545
} else {
4646
break;
4747
}

ytt_generator.h

Lines changed: 93 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,31 @@
2424
#include "magic_enum.hpp"
2525

2626

27+
// Returns the number of UTF‑8 code points in s.
2728
int utf8_length(const std::string &s) {
2829
return static_cast<int>(utf8::distance(s.begin(), s.end()));
2930
}
3031

32+
// Returns the first 'count' UTF‑8 code points of s.
3133
std::string utf8_substr(const std::string &s, int count) {
3234
auto it = s.begin();
3335
int i = 0;
3436
while (it != s.end() && i < count) {
3537
utf8::next(it, s.end());
3638
++i;
3739
}
38-
return std::string(s.begin(), it);
40+
return {s.begin(), it};
41+
}
42+
43+
// Returns the remainder of s after consuming the first 'count' UTF‑8 code points.
44+
std::string utf8_consume(const std::string &s, int count) {
45+
auto it = s.begin();
46+
int i = 0;
47+
while (it != s.end() && i < count) {
48+
utf8::next(it, s.end());
49+
++i;
50+
}
51+
return {it, s.end()};
3952
}
4053

4154
template<typename T, T Max>
@@ -400,73 +413,70 @@ struct Batch {
400413
std::deque<ChatLine> lines;
401414
};
402415

403-
404-
std::vector<std::string> wrapText(const std::string &text, int maxChars, int prefixSize) {
416+
std::pair<std::string, std::vector<std::string>> wrapMessage(std::string username,
417+
std::string separator,
418+
const std::string &message,
419+
int maxWidth) {
405420
std::vector<std::string> lines;
406-
if (text.empty() || maxChars <= 0 || prefixSize >= maxChars)
407-
return lines;
421+
int availableSpace = maxWidth;
422+
if (utf8_length(username) > maxWidth) {
423+
username = utf8_substr(username, maxWidth);
424+
lines.push_back("");
425+
} else {
426+
availableSpace -= utf8_length(username);
427+
}
428+
if (utf8_length(separator) > availableSpace) {
429+
separator = utf8_substr(separator, availableSpace);
430+
}
431+
if (utf8_length(separator) > 0) {
432+
lines.push_back(separator);
433+
availableSpace -= utf8_length(separator);
434+
}
408435

409-
int firstLineMaxChars = maxChars - prefixSize;
410-
std::istringstream iss(text);
436+
std::istringstream iss(message);
437+
std::vector<std::string> words;
411438
std::string word;
412-
std::string line;
413-
bool isFirstLine = true;
414-
439+
bool firstWord = true;
415440
while (iss >> word) {
416-
int currentMaxChars = isFirstLine ? firstLineMaxChars : maxChars;
417-
int lineLen = utf8_length(line);
418-
int wordLen = utf8_length(word);
419-
420-
if (!line.empty() && (lineLen + 1 + wordLen > currentMaxChars)) {
421-
lines.push_back(line);
422-
line.clear();
423-
isFirstLine = false;
424-
}
425-
426-
427-
if (wordLen > currentMaxChars) {
428-
if (!line.empty()) {
429-
lines.push_back(line);
430-
line.clear();
431-
isFirstLine = false;
432-
}
433-
auto wordIt = word.begin();
434-
while (wordIt != word.end()) {
435-
auto startIt = wordIt;
436-
int count = 0;
437-
while (wordIt != word.end() && count < currentMaxChars) {
438-
utf8::next(wordIt, word.end());
439-
++count;
441+
bool bigWord = false;
442+
while (utf8_length(word) > maxWidth) {
443+
bigWord = true;
444+
if (availableSpace < 2) {
445+
availableSpace = maxWidth;
446+
lines.push_back(utf8_substr(word, availableSpace));
447+
firstWord = false;
448+
449+
} else {
450+
451+
if (!firstWord) {
452+
lines.back() += " ";
453+
availableSpace--;
440454
}
441-
lines.emplace_back(startIt, wordIt);
442-
currentMaxChars = maxChars;
443-
isFirstLine = false;
455+
lines.back() += utf8_substr(word, availableSpace);
456+
firstWord = false;
444457
}
458+
word = utf8_consume(word, availableSpace);// add split
459+
availableSpace = 0;
460+
}
461+
if (bigWord) {
462+
//if (utf8_length(word) < availableSpace) word += " ";
463+
lines.push_back(word);
464+
availableSpace = maxWidth - utf8_length(word);
465+
firstWord = false;
445466
continue;
446467
}
447-
448-
if (!line.empty()) {
449-
line.append(" ");
468+
if (utf8_length(word) < availableSpace) {
469+
if (!firstWord) lines.back() += " ";
470+
lines.back() += word;
471+
availableSpace -= utf8_length(word);
472+
} else {
473+
//if (utf8_length(word) < maxWidth) word += " ";
474+
lines.push_back(word);
475+
availableSpace = maxWidth - utf8_length(word);
450476
}
451-
line.append(word);
452-
}
453-
454-
if (!line.empty())
455-
lines.push_back(line);
456-
return lines;
457-
}
458-
459-
std::vector<std::string> wrapMessage(std::string &username,
460-
const std::string &usernameSeparator,
461-
const std::string &message,
462-
int maxCharsPerLine) {
463-
if (utf8_length(username) > maxCharsPerLine) {
464-
int charsToKeep = maxCharsPerLine - utf8_length(usernameSeparator);
465-
if (charsToKeep < 0) charsToKeep = 0;
466-
username = utf8_substr(username, charsToKeep);
467-
477+
firstWord = false;
468478
}
469-
return wrapText(usernameSeparator + message, maxCharsPerLine, utf8_length(username));;
479+
return {username, lines};
470480
}
471481

472482

@@ -483,8 +493,9 @@ std::string generateXML(const std::vector<ChatMessage> &messages, const ChatPara
483493
std::vector<Batch> batches;
484494
std::deque<ChatLine> currentLines;
485495
for (const auto &msg: messages) {
486-
std::string username = msg.user.name;
487-
auto wrapped = wrapMessage(username, params.usernameSeparator, msg.message, params.maxCharsPerLine);
496+
497+
auto [username, wrapped] = wrapMessage(msg.user.name, params.usernameSeparator, msg.message,
498+
params.maxCharsPerLine);
488499
if (wrapped.empty())
489500
continue;
490501

@@ -605,5 +616,27 @@ Color getRandomColor(const std::string &username) {
605616

606617
}
607618

619+
int test() {
620+
// Example inputs.
621+
std::string username = "Alice1234";
622+
std::string separator = ": ";
623+
std::string message = "Hello this is a long message that we will try to wrap correctly even if there are verylongwordswithoutanyspaces";
624+
int maxWidth = 30;
625+
626+
auto [displayName, wrappedLines] = wrapMessage(username, separator, message, maxWidth);
627+
628+
// Print the results.
629+
std::cout << "Username: " << displayName << "\n";
630+
std::cout << "Message:\n";
631+
// Print the full first line as it would appear when concatenated.
632+
std::string fullFirstLine = displayName + wrappedLines[0];
633+
std::cout << fullFirstLine << "|" << utf8_length(fullFirstLine) << "\n";
634+
for (size_t i = 1; i < wrappedLines.size(); ++i) {
635+
std::cout << wrappedLines[i] << "|" << utf8_length(wrappedLines[i]) << "\n";
636+
}
637+
638+
return 0;
639+
}
640+
608641

609642

0 commit comments

Comments
 (0)