Merge pull request #64564 from timothyqiu/word-wrap-3.x
[3.x] Fix `String::word_wrap()` for long words
This commit is contained in:
commit
4769aa4499
2 changed files with 87 additions and 21 deletions
|
@ -3428,33 +3428,63 @@ bool String::is_valid_identifier() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//kind of poor should be rewritten properly
|
|
||||||
|
|
||||||
String String::word_wrap(int p_chars_per_line) const {
|
String String::word_wrap(int p_chars_per_line) const {
|
||||||
int from = 0;
|
|
||||||
int last_space = 0;
|
|
||||||
String ret;
|
String ret;
|
||||||
|
|
||||||
|
int line_start = 0;
|
||||||
|
int line_end = 0; // End of last word on current line.
|
||||||
|
int word_start = 0; // -1 if no word encountered. Leading spaces are part of a word.
|
||||||
|
int word_length = 0;
|
||||||
|
|
||||||
for (int i = 0; i < length(); i++) {
|
for (int i = 0; i < length(); i++) {
|
||||||
if (i - from >= p_chars_per_line) {
|
const CharType c = operator[](i);
|
||||||
if (last_space == -1) {
|
|
||||||
ret += substr(from, i - from + 1) + "\n";
|
switch (c) {
|
||||||
} else {
|
case '\n': {
|
||||||
ret += substr(from, last_space - from) + "\n";
|
// Force newline.
|
||||||
i = last_space; //rewind
|
ret += substr(line_start, i - line_start + 1);
|
||||||
}
|
line_start = i + 1;
|
||||||
from = i + 1;
|
line_end = line_start;
|
||||||
last_space = -1;
|
word_start = line_start;
|
||||||
} else if (operator[](i) == ' ' || operator[](i) == '\t') {
|
word_length = 0;
|
||||||
last_space = i;
|
} break;
|
||||||
} else if (operator[](i) == '\n') {
|
|
||||||
ret += substr(from, i - from) + "\n";
|
case ' ':
|
||||||
from = i + 1;
|
case '\t': {
|
||||||
last_space = -1;
|
// A whitespace ends current word.
|
||||||
|
if (word_length > 0) {
|
||||||
|
line_end = i - 1;
|
||||||
|
word_start = -1;
|
||||||
|
word_length = 0;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
if (word_start == -1) {
|
||||||
|
word_start = i;
|
||||||
|
}
|
||||||
|
word_length += 1;
|
||||||
|
|
||||||
|
if (word_length > p_chars_per_line) {
|
||||||
|
// Word too long: wrap before current character.
|
||||||
|
ret += substr(line_start, i - line_start) + "\n";
|
||||||
|
line_start = i;
|
||||||
|
line_end = i;
|
||||||
|
word_start = i;
|
||||||
|
word_length = 1;
|
||||||
|
} else if (i - line_start + 1 > p_chars_per_line) {
|
||||||
|
// Line too long: wrap after the last word.
|
||||||
|
ret += substr(line_start, line_end - line_start + 1) + "\n";
|
||||||
|
line_start = word_start;
|
||||||
|
line_end = line_start;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from < length()) {
|
const int remaining = length() - line_start;
|
||||||
ret += substr(from, length());
|
if (remaining) {
|
||||||
|
ret += substr(line_start, remaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1219,6 +1219,41 @@ bool test_36() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_37() {
|
||||||
|
#define CHECK_EQ(X, Y) \
|
||||||
|
if ((X) != (Y)) { \
|
||||||
|
OS::get_singleton()->print("\tFAIL: %s != %s\n", #X, #Y); \
|
||||||
|
return false; \
|
||||||
|
} else { \
|
||||||
|
OS::get_singleton()->print("\tPASS\n"); \
|
||||||
|
}
|
||||||
|
OS::get_singleton()->print("\n\nTest 37: Word wrap\n");
|
||||||
|
|
||||||
|
// Long words.
|
||||||
|
CHECK_EQ(String("12345678").word_wrap(8), "12345678");
|
||||||
|
CHECK_EQ(String("1234567812345678").word_wrap(8), "12345678\n12345678");
|
||||||
|
CHECK_EQ(String("123456781234567812345678").word_wrap(8), "12345678\n12345678\n12345678");
|
||||||
|
|
||||||
|
// Long line.
|
||||||
|
CHECK_EQ(String("123 567 123456 123").word_wrap(8), "123 567\n123456\n123");
|
||||||
|
|
||||||
|
// Force newline at line length should not create another newline.
|
||||||
|
CHECK_EQ(String("12345678 123").word_wrap(8), "12345678\n123");
|
||||||
|
CHECK_EQ(String("12345678\n123").word_wrap(8), "12345678\n123");
|
||||||
|
|
||||||
|
// Wrapping removes spaces.
|
||||||
|
CHECK_EQ(String("1234567 123").word_wrap(8), "1234567\n123");
|
||||||
|
CHECK_EQ(String("12345678 123").word_wrap(8), "12345678\n123");
|
||||||
|
|
||||||
|
// Wrapping does not remove leading space.
|
||||||
|
CHECK_EQ(String(" 123456 123 12").word_wrap(8), " 123456\n123 12");
|
||||||
|
CHECK_EQ(String(" 123456\n 456 12").word_wrap(8), " 123456\n 456\n12");
|
||||||
|
CHECK_EQ(String(" 123456\n 4 12345678").word_wrap(8), " 123456\n 4\n12345678");
|
||||||
|
CHECK_EQ(String(" 123456\n 4 12345678123").word_wrap(8), " 123456\n 4\n12345678\n123");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
typedef bool (*TestFunc)();
|
typedef bool (*TestFunc)();
|
||||||
|
|
||||||
TestFunc test_funcs[] = {
|
TestFunc test_funcs[] = {
|
||||||
|
@ -1259,6 +1294,7 @@ TestFunc test_funcs[] = {
|
||||||
test_34,
|
test_34,
|
||||||
test_35,
|
test_35,
|
||||||
test_36,
|
test_36,
|
||||||
|
test_37,
|
||||||
nullptr
|
nullptr
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue