get_wraped_wxString(): Adapted to work with UTF8

This commit is contained in:
Vojtech Bubnik 2022-01-31 16:25:20 +01:00
parent 1fe9e5231b
commit be60775077
3 changed files with 66 additions and 50 deletions

View File

@ -77,6 +77,7 @@ extern std::string normalize_utf8_nfc(const char *src);
// Returns next utf8 sequence length. =number of bytes in string, that creates together one utf-8 character. // Returns next utf8 sequence length. =number of bytes in string, that creates together one utf-8 character.
// Starting at pos. ASCII characters returns 1. Works also if pos is in the middle of the sequence. // Starting at pos. ASCII characters returns 1. Works also if pos is in the middle of the sequence.
extern size_t get_utf8_sequence_length(const std::string& text, size_t pos = 0); extern size_t get_utf8_sequence_length(const std::string& text, size_t pos = 0);
extern size_t get_utf8_sequence_length(const char *seq, size_t size);
// Safely rename a file even if the target exists. // Safely rename a file even if the target exists.
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file // On Windows, the file explorer (or anti-virus or whatever else) often locks the file

View File

@ -866,8 +866,13 @@ std::string normalize_utf8_nfc(const char *src)
size_t get_utf8_sequence_length(const std::string& text, size_t pos) size_t get_utf8_sequence_length(const std::string& text, size_t pos)
{ {
assert(pos < text.size()); assert(pos < text.size());
return get_utf8_sequence_length(text.c_str() + pos, text.size() - pos);
}
size_t get_utf8_sequence_length(const char *seq, size_t size)
{
size_t length = 0; size_t length = 0;
unsigned char c = text[pos]; unsigned char c = seq[0];
if (c < 0x80) { // 0x00-0x7F if (c < 0x80) { // 0x00-0x7F
// is ASCII letter // is ASCII letter
length++; length++;
@ -876,8 +881,8 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos)
// pos is in the middle of a utf-8 sequence. Add the utf-8 trailer bytes. // pos is in the middle of a utf-8 sequence. Add the utf-8 trailer bytes.
else if (c < 0xC0) { // 0x80-0xBF else if (c < 0xC0) { // 0x80-0xBF
length++; length++;
while (pos + length < text.size()) { while (length < size) {
c = text[pos + length]; c = seq[length];
if (c < 0x80 || c >= 0xC0) { if (c < 0x80 || c >= 0xC0) {
break; // prevent overrun break; // prevent overrun
} }
@ -888,36 +893,36 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos)
// The number of one bits above the topmost zero bit indicates the number of bytes (including this one) in the whole sequence. // The number of one bits above the topmost zero bit indicates the number of bytes (including this one) in the whole sequence.
else if (c < 0xE0) { // 0xC0-0xDF else if (c < 0xE0) { // 0xC0-0xDF
// add a utf-8 sequence (2 bytes) // add a utf-8 sequence (2 bytes)
if (pos + 2 > text.size()) { if (2 > size) {
return text.size() - pos; // prevent overrun return size; // prevent overrun
} }
length += 2; length += 2;
} }
else if (c < 0xF0) { // 0xE0-0xEF else if (c < 0xF0) { // 0xE0-0xEF
// add a utf-8 sequence (3 bytes) // add a utf-8 sequence (3 bytes)
if (pos + 3 > text.size()) { if (3 > size) {
return text.size() - pos; // prevent overrun return size; // prevent overrun
} }
length += 3; length += 3;
} }
else if (c < 0xF8) { // 0xF0-0xF7 else if (c < 0xF8) { // 0xF0-0xF7
// add a utf-8 sequence (4 bytes) // add a utf-8 sequence (4 bytes)
if (pos + 4 > text.size()) { if (4 > size) {
return text.size() - pos; // prevent overrun return size; // prevent overrun
} }
length += 4; length += 4;
} }
else if (c < 0xFC) { // 0xF8-0xFB else if (c < 0xFC) { // 0xF8-0xFB
// add a utf-8 sequence (5 bytes) // add a utf-8 sequence (5 bytes)
if (pos + 5 > text.size()) { if (5 > size) {
return text.size() - pos; // prevent overrun return size; // prevent overrun
} }
length += 5; length += 5;
} }
else if (c < 0xFE) { // 0xFC-0xFD else if (c < 0xFE) { // 0xFC-0xFD
// add a utf-8 sequence (6 bytes) // add a utf-8 sequence (6 bytes)
if (pos + 6 > text.size()) { if (6 > size) {
return text.size() - pos; // prevent overrun return size; // prevent overrun
} }
length += 6; length += 6;
} }

View File

@ -291,48 +291,58 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString&
finalize(); finalize();
} }
wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/) wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
{ {
#ifdef __WXMSW__ wxString out;
static constexpr const char slash = '\\';
for (size_t i = 0; i < in.size();) {
// Overwrite the character (space or newline) starting at ibreak?
bool overwrite = false;
#if wxUSE_UNICODE_WCHAR
// On Windows, most likely the internal representation of wxString is wide char.
size_t end = std::min(in.size(), i + line_len);
size_t ibreak = end;
for (size_t j = i; j < end; ++ j) {
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
ibreak = j;
overwrite = true;
if (newline)
break;
} else if (in[j] == '/' || in[j] == '\\')
ibreak = j + 1;
}
#else #else
static constexpr const char slash = '/'; // UTF8 representation of wxString.
// Where to break the line, index of character at the start of a UTF-8 sequence.
size_t ibreak = size_t(-1);
// Overwrite the character at ibreak (it is a whitespace) or not?
for (size_t cnt = 0, j = i; j < in.size();) {
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
// Overwrite the whitespace.
ibreak = j ++;
overwrite = true;
if (newline)
break;
} else if (in[j] == '/') {
// Insert after the slash.
ibreak = ++ j;
} else
j += get_utf8_sequence_length(in.c_str() + j, in.size() - j);
if (++ cnt == line_len) {
if (ibreak == size_t(-1))
ibreak = j;
break;
}
}
#endif #endif
static constexpr const char space = ' '; out.append(in.begin() + i, in.begin() + ibreak);
static constexpr const char new_line = '\n'; out.append('\n');
i = ibreak;
if (overwrite)
++ i;
}
wxString text = text_in; return out;
size_t idx = 0;
size_t cur_len = 0;
size_t text_len = text.size();
for (size_t i = 0; i < text_len; ++ i) {
if (text[i] == new_line) {
idx = i;
cur_len = 0;
} else {
++ cur_len;
if (text[i] == space || text[i] == slash)
idx = i;
if (cur_len >= line_len) {
cur_len = i - idx;
if (cur_len >= line_len) {
text.insert(++i, 1, new_line);
idx = i;
cur_len = 0;
}
else if (text[idx] == slash) {
text.insert(++idx, 1, new_line);
++text_len;
++i;
}
else // space
text[idx] = new_line;
}
}
}
return text;
} }
} }