diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/enriched_string.cpp | 88 | ||||
-rw-r--r-- | src/util/enriched_string.h | 28 | ||||
-rw-r--r-- | src/util/string.cpp | 123 | ||||
-rw-r--r-- | src/util/string.h | 19 |
4 files changed, 127 insertions, 131 deletions
diff --git a/src/util/enriched_string.cpp b/src/util/enriched_string.cpp index 642188a52..762d094eb 100644 --- a/src/util/enriched_string.cpp +++ b/src/util/enriched_string.cpp @@ -19,7 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "enriched_string.h" #include "util/string.h" +#include "debug.h" #include "log.h" + using namespace irr::video; EnrichedString::EnrichedString() @@ -28,10 +30,12 @@ EnrichedString::EnrichedString() } EnrichedString::EnrichedString(const std::wstring &string, - const std::vector<SColor> &colors): - m_string(string), - m_colors(colors) -{} + const std::vector<SColor> &colors) +{ + clear(); + m_string = string; + m_colors = colors; +} EnrichedString::EnrichedString(const std::wstring &s, const SColor &color) { @@ -45,15 +49,28 @@ EnrichedString::EnrichedString(const wchar_t *str, const SColor &color) addAtEnd(translate_string(std::wstring(str)), color); } +void EnrichedString::clear() +{ + m_string.clear(); + m_colors.clear(); + m_has_background = false; + m_default_length = 0; + m_default_color = irr::video::SColor(255, 255, 255, 255); + m_background = irr::video::SColor(0, 0, 0, 0); +} + void EnrichedString::operator=(const wchar_t *str) { clear(); - addAtEnd(translate_string(std::wstring(str)), SColor(255, 255, 255, 255)); + addAtEnd(translate_string(std::wstring(str)), m_default_color); } void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color) { SColor color(initial_color); + bool use_default = (m_default_length == m_string.size() && + color == m_default_color); + size_t i = 0; while (i < s.length()) { if (s[i] != L'\x1b') { @@ -90,6 +107,12 @@ void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color continue; } parseColorString(wide_to_utf8(parts[1]), color, true); + + // No longer use default color after first escape + if (use_default) { + m_default_length = m_string.size(); + use_default = false; + } } else if (parts[0] == L"b") { if (parts.size() < 2) { continue; @@ -98,6 +121,10 @@ void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color m_has_background = true; } } + + // Update if no escape character was found + if (use_default) + m_default_length = m_string.size(); } void EnrichedString::addChar(const EnrichedString &source, size_t i) @@ -110,7 +137,7 @@ void EnrichedString::addCharNoColor(wchar_t c) { m_string += c; if (m_colors.empty()) { - m_colors.emplace_back(255, 255, 255, 255); + m_colors.emplace_back(m_default_color); } else { m_colors.push_back(m_colors[m_colors.size() - 1]); } @@ -118,35 +145,44 @@ void EnrichedString::addCharNoColor(wchar_t c) EnrichedString EnrichedString::operator+(const EnrichedString &other) const { - std::vector<SColor> result; - result.insert(result.end(), m_colors.begin(), m_colors.end()); - result.insert(result.end(), other.m_colors.begin(), other.m_colors.end()); - return EnrichedString(m_string + other.m_string, result); + EnrichedString result = *this; + result += other; + return result; } void EnrichedString::operator+=(const EnrichedString &other) { + bool update_default_color = m_default_length == m_string.size(); + m_string += other.m_string; m_colors.insert(m_colors.end(), other.m_colors.begin(), other.m_colors.end()); + + if (update_default_color) { + m_default_length += other.m_default_length; + updateDefaultColor(); + } } EnrichedString EnrichedString::substr(size_t pos, size_t len) const { - if (pos == m_string.length()) { + if (pos >= m_string.length()) return EnrichedString(); - } - if (len == std::string::npos || pos + len > m_string.length()) { - return EnrichedString( - m_string.substr(pos, std::string::npos), - std::vector<SColor>(m_colors.begin() + pos, m_colors.end()) - ); - } - return EnrichedString( + if (len == std::string::npos || pos + len > m_string.length()) + len = m_string.length() - pos; + + EnrichedString str( m_string.substr(pos, len), std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len) ); + str.m_has_background = m_has_background; + str.m_background = m_background; + + if (pos < m_default_length) + str.m_default_length = std::min(m_default_length - pos, str.size()); + str.setDefaultColor(m_default_color); + return str; } const wchar_t *EnrichedString::c_str() const @@ -163,3 +199,17 @@ const std::wstring &EnrichedString::getString() const { return m_string; } + +void EnrichedString::setDefaultColor(const irr::video::SColor &color) +{ + m_default_color = color; + updateDefaultColor(); +} + +void EnrichedString::updateDefaultColor() +{ + sanity_check(m_default_length <= m_colors.size()); + + for (size_t i = 0; i < m_default_length; ++i) + m_colors[i] = m_default_color; +} diff --git a/src/util/enriched_string.h b/src/util/enriched_string.h index 202d84cb0..c8a095887 100644 --- a/src/util/enriched_string.h +++ b/src/util/enriched_string.h @@ -32,6 +32,7 @@ public: const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255)); EnrichedString(const std::wstring &string, const std::vector<irr::video::SColor> &colors); + void clear(); void operator=(const wchar_t *str); void addAtEnd(const std::wstring &s, const irr::video::SColor &color); @@ -50,6 +51,14 @@ public: const wchar_t *c_str() const; const std::vector<irr::video::SColor> &getColors() const; const std::wstring &getString() const; + + void setDefaultColor(const irr::video::SColor &color); + void updateDefaultColor(); + inline const irr::video::SColor &getDefaultColor() const + { + return m_default_color; + } + inline bool operator==(const EnrichedString &other) const { return (m_string == other.m_string && m_colors == other.m_colors); @@ -58,12 +67,6 @@ public: { return !(*this == other); } - inline void clear() - { - m_string.clear(); - m_colors.clear(); - m_has_background = false; - } inline bool empty() const { return m_string.empty(); @@ -72,6 +75,7 @@ public: { return m_string.size(); } + inline bool hasBackground() const { return m_has_background; @@ -80,9 +84,19 @@ public: { return m_background; } + inline void setBackground(const irr::video::SColor &color) + { + m_background = color; + m_has_background = true; + } + private: std::wstring m_string; std::vector<irr::video::SColor> m_colors; - bool m_has_background = false; + bool m_has_background; + irr::video::SColor m_default_color; irr::video::SColor m_background; + // This variable defines the length of the default-colored text. + // Change this to a std::vector if an "end coloring" tag is wanted. + size_t m_default_length = 0; }; diff --git a/src/util/string.cpp b/src/util/string.cpp index 388e8d293..e6c52585d 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -79,6 +79,13 @@ bool convert(const char *to, const char *from, char *outbuf, return true; } +#ifdef __ANDROID__ +// Android need manual caring to support the full character set possible with wchar_t +const char *DEFAULT_ENCODING = "UTF-32LE"; +#else +const char *DEFAULT_ENCODING = "WCHAR_T"; +#endif + std::wstring utf8_to_wide(const std::string &input) { size_t inbuf_size = input.length() + 1; @@ -90,7 +97,12 @@ std::wstring utf8_to_wide(const std::string &input) char *outbuf = new char[outbuf_size]; memset(outbuf, 0, outbuf_size); - if (!convert("WCHAR_T", "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size)) { +#ifdef __ANDROID__ + // Android need manual caring to support the full character set possible with wchar_t + SANITY_CHECK(sizeof(wchar_t) == 4); +#endif + + if (!convert(DEFAULT_ENCODING, "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size)) { infostream << "Couldn't convert UTF-8 string 0x" << hex_encode(input) << " into wstring" << std::endl; delete[] inbuf; @@ -105,13 +117,6 @@ std::wstring utf8_to_wide(const std::string &input) return out; } -#ifdef __ANDROID__ -// TODO: this is an ugly fix for wide_to_utf8 somehow not working on android -std::string wide_to_utf8(const std::wstring &input) -{ - return wide_to_narrow(input); -} -#else std::string wide_to_utf8(const std::wstring &input) { size_t inbuf_size = (input.length() + 1) * sizeof(wchar_t); @@ -123,7 +128,7 @@ std::string wide_to_utf8(const std::wstring &input) char *outbuf = new char[outbuf_size]; memset(outbuf, 0, outbuf_size); - if (!convert("UTF-8", "WCHAR_T", outbuf, outbuf_size, inbuf, inbuf_size)) { + if (!convert("UTF-8", DEFAULT_ENCODING, outbuf, outbuf_size, inbuf, inbuf_size)) { infostream << "Couldn't convert wstring 0x" << hex_encode(inbuf, inbuf_size) << " into UTF-8 string" << std::endl; delete[] inbuf; @@ -138,7 +143,6 @@ std::string wide_to_utf8(const std::wstring &input) return out; } -#endif #else // _WIN32 std::wstring utf8_to_wide(const std::string &input) @@ -183,7 +187,7 @@ wchar_t *utf8_to_wide_c(const char *str) // The returned string is allocated using new wchar_t *narrow_to_wide_c(const char *str) { - wchar_t *nstr = NULL; + wchar_t *nstr = nullptr; #if defined(_WIN32) int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, 0, 0); if (nResult == 0) { @@ -204,67 +208,8 @@ wchar_t *narrow_to_wide_c(const char *str) return nstr; } - -#ifdef __ANDROID__ - -const wchar_t* wide_chars = - L" !\"#$%&'()*+,-./0123456789:;<=>?@" - L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" - L"abcdefghijklmnopqrstuvwxyz{|}~"; - -int wctomb(char *s, wchar_t wc) -{ - for (unsigned int j = 0; j < (sizeof(wide_chars)/sizeof(wchar_t));j++) { - if (wc == wide_chars[j]) { - *s = (char) (j+32); - return 1; - } - else if (wc == L'\n') { - *s = '\n'; - return 1; - } - } - return -1; -} - -int mbtowc(wchar_t *pwc, const char *s, size_t n) -{ - std::wstring intermediate = narrow_to_wide(s); - - if (intermediate.length() > 0) { - *pwc = intermediate[0]; - return 1; - } - else { - return -1; - } -} - std::wstring narrow_to_wide(const std::string &mbs) { size_t wcl = mbs.size(); - - std::wstring retval = L""; - - for (unsigned int i = 0; i < wcl; i++) { - if (((unsigned char) mbs[i] >31) && - ((unsigned char) mbs[i] < 127)) { - - retval += wide_chars[(unsigned char) mbs[i] -32]; - } - //handle newline - else if (mbs[i] == '\n') { - retval += L'\n'; - } - } - - return retval; -} - -#else // not Android - -std::wstring narrow_to_wide(const std::string &mbs) -{ - size_t wcl = mbs.size(); Buffer<wchar_t> wcs(wcl + 1); size_t len = mbstowcs(*wcs, mbs.c_str(), wcl); if (len == (size_t)(-1)) @@ -273,37 +218,6 @@ std::wstring narrow_to_wide(const std::string &mbs) return *wcs; } -#endif - -#ifdef __ANDROID__ - -std::string wide_to_narrow(const std::wstring &wcs) { - size_t mbl = wcs.size()*4; - - std::string retval = ""; - for (unsigned int i = 0; i < wcs.size(); i++) { - wchar_t char1 = (wchar_t) wcs[i]; - - if (char1 == L'\n') { - retval += '\n'; - continue; - } - - for (unsigned int j = 0; j < wcslen(wide_chars);j++) { - wchar_t char2 = (wchar_t) wide_chars[j]; - - if (char1 == char2) { - char toadd = (j+32); - retval += toadd; - break; - } - } - } - - return retval; -} - -#else // not Android std::string wide_to_narrow(const std::wstring &wcs) { @@ -317,7 +231,6 @@ std::string wide_to_narrow(const std::wstring &wcs) return *mbs; } -#endif std::string urlencode(const std::string &str) { @@ -361,10 +274,10 @@ u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask) u32 mask = 0; char *s = &str[0]; char *flagstr; - char *strpos = NULL; + char *strpos = nullptr; while ((flagstr = strtok_r(s, ",", &strpos))) { - s = NULL; + s = nullptr; while (*flagstr == ' ' || *flagstr == '\t') flagstr++; @@ -436,7 +349,7 @@ char *mystrtok_r(char *s, const char *sep, char **lasts) s++; if (!*s) - return NULL; + return nullptr; t = s; while (*t) { diff --git a/src/util/string.h b/src/util/string.h index ab9a4a6c8..0d2a6bdb2 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include "irrlichttypes_bloated.h" +#include "irrString.h" #include <cstdlib> #include <string> #include <cstring> @@ -723,3 +724,21 @@ inline std::string str_join(const std::vector<std::string> &list, } return oss.str(); } + +/** + * Create a UTF8 std::string from a irr::core::stringw. + */ +inline std::string stringw_to_utf8(const irr::core::stringw &input) +{ + std::wstring str(input.c_str()); + return wide_to_utf8(str); +} + + /** + * Create a irr::core:stringw from a UTF8 std::string. + */ +inline irr::core::stringw utf8_to_stringw(const std::string &input) +{ + std::wstring str = utf8_to_wide(input); + return irr::core::stringw(str.c_str()); +} |