From be60775077f08a1cc3b58a1e32b6923cdee15873 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 16:25:20 +0100 Subject: [PATCH] get_wraped_wxString(): Adapted to work with UTF8 --- src/libslic3r/Utils.hpp | 1 + src/libslic3r/utils.cpp | 31 +++++++------ src/slic3r/GUI/MsgDialog.cpp | 84 ++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index d9419495e..1de3a5ef8 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -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. // 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 char *seq, size_t size); // Safely rename a file even if the target exists. // On Windows, the file explorer (or anti-virus or whatever else) often locks the file diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index c74e57e99..e00b6e71c 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -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) { 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; - unsigned char c = text[pos]; + unsigned char c = seq[0]; if (c < 0x80) { // 0x00-0x7F // is ASCII letter 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. else if (c < 0xC0) { // 0x80-0xBF length++; - while (pos + length < text.size()) { - c = text[pos + length]; + while (length < size) { + c = seq[length]; if (c < 0x80 || c >= 0xC0) { 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. else if (c < 0xE0) { // 0xC0-0xDF // add a utf-8 sequence (2 bytes) - if (pos + 2 > text.size()) { - return text.size() - pos; // prevent overrun + if (2 > size) { + return size; // prevent overrun } length += 2; } else if (c < 0xF0) { // 0xE0-0xEF // add a utf-8 sequence (3 bytes) - if (pos + 3 > text.size()) { - return text.size() - pos; // prevent overrun + if (3 > size) { + return size; // prevent overrun } length += 3; } else if (c < 0xF8) { // 0xF0-0xF7 // add a utf-8 sequence (4 bytes) - if (pos + 4 > text.size()) { - return text.size() - pos; // prevent overrun + if (4 > size) { + return size; // prevent overrun } length += 4; } else if (c < 0xFC) { // 0xF8-0xFB // add a utf-8 sequence (5 bytes) - if (pos + 5 > text.size()) { - return text.size() - pos; // prevent overrun + if (5 > size) { + return size; // prevent overrun } length += 5; } else if (c < 0xFE) { // 0xFC-0xFD // add a utf-8 sequence (6 bytes) - if (pos + 6 > text.size()) { - return text.size() - pos; // prevent overrun + if (6 > size) { + return size; // prevent overrun } length += 6; } diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index dad88f14b..db4972a5d 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -291,48 +291,58 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString& 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__ - static constexpr const char slash = '\\'; -#else - static constexpr const char slash = '/'; -#endif - static constexpr const char space = ' '; - static constexpr const char new_line = '\n'; + wxString out; - wxString text = text_in; - - 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; + 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 + // 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 + out.append(in.begin() + i, in.begin() + ibreak); + out.append('\n'); + i = ibreak; + if (overwrite) + ++ i; } - return text; + + return out; } }