diff --git a/nel/include/nel/3d/computed_string.h b/nel/include/nel/3d/computed_string.h index 3f27a2879..c4404f661 100644 --- a/nel/include/nel/3d/computed_string.h +++ b/nel/include/nel/3d/computed_string.h @@ -181,7 +181,7 @@ public: CVertexBuffer Vertices; CMaterial *Material; CRGBA Color; - ucstring Text; + std::string Text; uint32 CacheVersion; diff --git a/nel/include/nel/3d/font_generator.h b/nel/include/nel/3d/font_generator.h index b69249d58..ea737afab 100644 --- a/nel/include/nel/3d/font_generator.h +++ b/nel/include/nel/3d/font_generator.h @@ -64,17 +64,17 @@ public: * \param height height of the generated bitmap, this value is set by this function * \param pitch pitch of the generated bitmap (+ or - the number of bytes per row), this value is set by this function */ - uint8 *getBitmap (ucchar c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex); + uint8 *getBitmap (u32char c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex); /** returns the width and height of a character using a specific size and * * \warning this function is not very fast (but faster than getBitmap()) because it has to load the char before. */ - void getSizes (ucchar c, uint32 size, uint32 &width, uint32 &height); + void getSizes (u32char c, uint32 size, uint32 &width, uint32 &height); - void getKerning (ucchar left, ucchar right, sint32 &kernx); + void getKerning (u32char left, u32char right, sint32 &kernx); - uint32 getCharIndex (ucchar c); + uint32 getCharIndex (u32char c); uint32 getUID() { return _UID; } diff --git a/nel/include/nel/3d/font_manager.h b/nel/include/nel/3d/font_manager.h index 663e9d23a..134df26f9 100644 --- a/nel/include/nel/3d/font_manager.h +++ b/nel/include/nel/3d/font_manager.h @@ -19,6 +19,7 @@ #include "nel/misc/types_nl.h" #include "nel/misc/smart_ptr.h" +#include "nel/misc/utf_string_view.h" #include "nel/3d/texture.h" #include "nel/3d/material.h" #include "nel/3d/texture_font.h" @@ -111,6 +112,7 @@ public: * \param output computed string * \param keep800x600Ratio true if you want that CFontManager look at Driver window size, and resize fontSize so it keeps same size... */ + /* void computeString (const std::string& s, CFontGenerator *fontGen, const NLMISC::CRGBA &color, @@ -120,11 +122,12 @@ public: IDriver *driver, CComputedString& output, bool keep800x600Ratio= true); + */ /** * Same as computeString but works with a unicode string (ucstring) */ - void computeString (const ucstring &s, + void computeString (NLMISC::CUtfStringView sv, CFontGenerator *fontGen, const NLMISC::CRGBA &color, uint32 fontSize, @@ -137,7 +140,21 @@ public: /** * Same as computeString but do not make vertex buffers and primitives */ - void computeStringInfo (const ucstring &s, + void computeStringInfo (NLMISC::CUtfStringView sv, + size_t len, + CFontGenerator *fontGen, + const NLMISC::CRGBA &color, + uint32 fontSize, + bool embolden, + bool oblique, + IDriver *driver, + CComputedString &output, + bool keep800x600Ratio= true); + + /** + * Same as computeString but do not make vertex buffers and primitives + */ + void computeStringInfo (NLMISC::CUtfStringView sv, CFontGenerator *fontGen, const NLMISC::CRGBA &color, uint32 fontSize, diff --git a/nel/include/nel/3d/text_context.h b/nel/include/nel/3d/text_context.h index 1eb256855..01a711e7e 100644 --- a/nel/include/nel/3d/text_context.h +++ b/nel/include/nel/3d/text_context.h @@ -134,7 +134,7 @@ public: uint32 textPush (const char *format, ...); /// computes an ucstring and adds the result to the cache (return the index) - uint32 textPush (const ucstring &str); + uint32 textPush (NLMISC::CUtfStringView sv); /// remove a string from the cache void erase (uint32 index); @@ -262,12 +262,12 @@ public: } /// Directly print a string - void printAt (float x, float z, const ucstring &ucstr) + void printAt (float x, float z, NLMISC::CUtfStringView sv) { nlassert(_FontGen); // compute the string just one time - _FontManager->computeString (ucstr, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, _TempString, _Keep800x600Ratio); + _FontManager->computeString (sv, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, _TempString, _Keep800x600Ratio); // draw shaded if (_Shaded) @@ -372,14 +372,19 @@ public: * \param an ucstring * \param the computed string */ - void computeString (const ucstring& s, CComputedString& output) + void computeString (NLMISC::CUtfStringView sv, CComputedString& output) { - _FontManager->computeString (s, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio); + _FontManager->computeString (sv, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio); + } + + void computeStringInfo (NLMISC::CUtfStringView sv, CComputedString& output) + { + _FontManager->computeStringInfo (sv, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio); } - void computeStringInfo (const ucstring& s, CComputedString& output) + void computeStringInfo (NLMISC::CUtfStringView sv, CComputedString& output, size_t len) { - _FontManager->computeStringInfo (s, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio); + _FontManager->computeStringInfo (sv, len, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, output, _Keep800x600Ratio); } /// Debug : write to the disk the texture cache diff --git a/nel/include/nel/3d/text_context_user.h b/nel/include/nel/3d/text_context_user.h index 2a167b2e9..039aebcd0 100644 --- a/nel/include/nel/3d/text_context_user.h +++ b/nel/include/nel/3d/text_context_user.h @@ -97,13 +97,14 @@ public: */ // @{ uint32 textPush(const char *format, ...) ; - uint32 textPush(const ucstring &str) ; + uint32 textPush(NLMISC::CUtfStringView sv) ; void setStringColor(uint32 i, CRGBA newCol); void setStringSelection(uint32 i, uint32 selectStart, uint32 selectSize); void resetStringSelection(uint32 i); void erase(uint32 i) ; virtual CStringInfo getStringInfo (uint32 i); - virtual CStringInfo getStringInfo (const ucstring &ucstr); + virtual CStringInfo getStringInfo (NLMISC::CUtfStringView sv); + virtual CStringInfo getStringInfo (NLMISC::CUtfStringView sv, size_t len); void clear() ; void printAt(float x, float y, uint32 i) ; @@ -111,10 +112,10 @@ public: void printClipAtUnProjected(URenderStringBuffer &renderBuffer, class NL3D::CFrustum &frustum, const NLMISC::CMatrix &scaleMatrix, float x, float y, float depth, uint32 i, float xmin, float ymin, float xmax, float ymax); void printClipAtOld (float x, float y, uint32 i, float xmin, float ymin, float xmax, float ymax); - void printAt(float x, float y, const ucstring &ucstr) ; + void printAt(float x, float y, NLMISC::CUtfStringView sv) ; void printfAt(float x, float y, const char * format, ...) ; - void render3D(const CMatrix &mat, const ucstring &ucstr) ; + void render3D(const CMatrix &mat, NLMISC::CUtfStringView sv) ; void render3D(const CMatrix &mat, const char *format, ...) ; float getLastXBound() const ; diff --git a/nel/include/nel/3d/texture_font.h b/nel/include/nel/3d/texture_font.h index 865615b63..5b0796721 100644 --- a/nel/include/nel/3d/texture_font.h +++ b/nel/include/nel/3d/texture_font.h @@ -69,7 +69,7 @@ public: // Holds info for glyphs displayed on screen struct SLetterInfo { - ucchar Char; + u32char Char; sint Size; bool Embolden; bool Oblique; @@ -94,7 +94,7 @@ public: struct SLetterKey { - ucchar Char; + u32char Char; sint Size; bool Embolden; bool Oblique; diff --git a/nel/include/nel/3d/u_text_context.h b/nel/include/nel/3d/u_text_context.h index cdde02f82..9cf710b11 100644 --- a/nel/include/nel/3d/u_text_context.h +++ b/nel/include/nel/3d/u_text_context.h @@ -24,7 +24,7 @@ #include "nel/misc/rgba.h" #include "nel/misc/ucstring.h" #include "nel/misc/matrix.h" - +#include "nel/misc/utf_string_view.h" namespace NL3D { @@ -248,7 +248,7 @@ public: * \param an ucstring * \return the index where computed string has been inserted */ - virtual uint32 textPush (const ucstring &str) = 0; + virtual uint32 textPush (NLMISC::CUtfStringView sv) = 0; /** * set the color of a string. */ @@ -274,7 +274,12 @@ public: * Get a string information from the ucstring * The returned string info is in pixel size per default. */ - virtual CStringInfo getStringInfo (const ucstring &ucstr) = 0; + virtual CStringInfo getStringInfo (NLMISC::CUtfStringView sv) = 0; + /** + * Get a string information from the ucstring + * The returned string info is in pixel size per default. + */ + virtual CStringInfo getStringInfo (NLMISC::CUtfStringView sv, size_t len) = 0; /** * empty the map */ @@ -299,7 +304,7 @@ public: /** * compute and print a ucstring at the location (2D method) x/y E [0,1] */ - virtual void printAt (float x, float y, const ucstring &ucstr) = 0; + virtual void printAt (float x, float y, NLMISC::CUtfStringView sv) = 0; /** * compute and print a string at the location (2D method) x/y E [0,1] */ @@ -309,7 +314,7 @@ public: * compute and render a ucstring at the location (3D method) * render3D() use UDriver Matrix context for Frustum/ViewMatrix, but use its own modelmatrix (mat). */ - virtual void render3D (const NLMISC::CMatrix &mat, const ucstring &ucstr) = 0; + virtual void render3D (const NLMISC::CMatrix &mat, NLMISC::CUtfStringView sv) = 0; /** * compute and render a string at the location (3D method) * render3D() use UDriver Matrix context for Frustum/ViewMatrix, but use its own modelmatrix (mat). diff --git a/nel/include/nel/gui/group_editbox.h b/nel/include/nel/gui/group_editbox.h index dc343410b..62b78584c 100644 --- a/nel/include/nel/gui/group_editbox.h +++ b/nel/include/nel/gui/group_editbox.h @@ -63,16 +63,16 @@ namespace NLGUI virtual bool handleEvent (const NLGUI::CEventDescriptor& eventDesc); /// Accessors - ucstring getInputString() const { return _InputString; } - const ucstring &getInputStringRef() const { return _InputString; } + u32string getInputString() const { return _InputString; } + const u32string &getInputStringRef() const { return _InputString; } const ucstring &getPrompt() const { return _Prompt; } /** Set the prompt * NB : line returns are encoded as '\n', not '\r\n' */ void setPrompt(const ucstring &s) { _Prompt = s; } - void setInputString(const ucstring &str); - void setInputStringRef(const ucstring &str) {_InputString = str; }; + void setInputString(const u32string &str); + void setInputStringRef(const u32string &str) {_InputString = str; }; void setInputStringAsInt(sint32 val); sint32 getInputStringAsInt() const; void setInputStringAsInt64(sint64 val); @@ -81,6 +81,8 @@ namespace NLGUI float getInputStringAsFloat() const; void setInputStringAsUtf8(const std::string &str); std::string getInputStringAsUtf8() const; + void setInputStringAsUtf16(const ucstring &str); + ucstring getInputStringAsUtf16() const; void setColor(NLMISC::CRGBA col); @@ -119,7 +121,7 @@ namespace NLGUI sint32 getMaxHistoric() const {return _MaxHistoric;} sint32 getCurrentHistoricIndex () const {return _CurrentHistoricIndex;} void setCurrentHistoricIndex (sint32 index) {_CurrentHistoricIndex=index;} - const ucstring &getHistoric(uint32 index) const {return _Historic[index];} + const u32string &getHistoric(uint32 index) const {return _Historic[index];} uint32 getNumHistoric() const {return (uint32)_Historic.size ();} // Get on change action handler @@ -188,7 +190,7 @@ namespace NLGUI REFLECT_LUA_METHOD("setFocusOnText", luaSetFocusOnText); REFLECT_LUA_METHOD("cancelFocusOnText", luaCancelFocusOnText); REFLECT_STRING("input_string", getInputStringAsUtf8, setInputStringAsUtf8); - REFLECT_UCSTRING("uc_input_string", getInputString, setInputString); + REFLECT_UCSTRING("uc_input_string", getInputStringAsUtf16, setInputStringAsUtf16); REFLECT_EXPORT_END /** Restore the original value of the edit box. @@ -227,16 +229,16 @@ namespace NLGUI // Text info ucstring _Prompt; - ucstring _InputString; + u32string _InputString; CViewText *_ViewText; // undo / redo - ucstring _StartInputString; // value of the input string when focus was acuired first - ucstring _ModifiedInputString; + u32string _StartInputString; // value of the input string when focus was acuired first + u32string _ModifiedInputString; // Historic info - typedef std::deque THistoric; + typedef std::deque THistoric; THistoric _Historic; uint32 _MaxHistoric; sint32 _CurrentHistoricIndex; diff --git a/nel/include/nel/misc/stream.h b/nel/include/nel/misc/stream.h index 35b6c3f26..89db78a1c 100644 --- a/nel/include/nel/misc/stream.h +++ b/nel/include/nel/misc/stream.h @@ -300,13 +300,6 @@ public: virtual void serial(bool &b) ; #ifndef NL_OS_CYGWIN virtual void serial(char &b) ; -#endif -#ifdef NL_OS_WINDOWS - inline void serial(wchar_t &b) - { - nlctassert(sizeof(wchar_t) == sizeof(uint16)); - serial(reinterpret_cast(b)); - } #endif virtual void serial(std::string &b) ; virtual void serial(ucstring &b) ; diff --git a/nel/include/nel/misc/types_nl.h b/nel/include/nel/misc/types_nl.h index 73c05b3a5..bac48c3d6 100644 --- a/nel/include/nel/misc/types_nl.h +++ b/nel/include/nel/misc/types_nl.h @@ -546,10 +546,14 @@ template<> struct hash * \typedef ucchar * An Unicode character (16 bits) */ -#if defined(NL_OS_WINDOWS) -typedef wchar_t ucchar; -#else typedef uint16 ucchar; + +#ifdef NL_CPP14 +typedef char32_t u32char; +typedef std::u32string u32string; +#else +typedef uint32 u32char; +typedef std::basic_string u32string; #endif #ifndef NL_OVERRIDE diff --git a/nel/include/nel/misc/ucstring.h b/nel/include/nel/misc/ucstring.h index 8859a21d9..5b7597f00 100644 --- a/nel/include/nel/misc/ucstring.h +++ b/nel/include/nel/misc/ucstring.h @@ -30,11 +30,7 @@ * An unicode string class (16 bits per character). * Add features to convert and assign \c ucstring to \c string and \c string to \c ucstring. */ -#if defined(NL_OS_WINDOWS) -typedef std::wstring ucstringbase; -#else typedef std::basic_string ucstringbase; -#endif class ucstring : public ucstringbase { @@ -46,6 +42,11 @@ public: { } + ucstring(const ucchar *begin, const ucchar *end) + : ucstringbase(begin, end) + { + } + ucstring(const std::string &str) : ucstringbase() { diff --git a/nel/include/nel/misc/utf_string_view.h b/nel/include/nel/misc/utf_string_view.h new file mode 100644 index 000000000..a23c2abca --- /dev/null +++ b/nel/include/nel/misc/utf_string_view.h @@ -0,0 +1,150 @@ +// NeL - MMORPG Framework +// Copyright (C) 2020 Jan BOON (Kaetemi) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NLMISC_UTF_STRING_VIEW_H +#define NLMISC_UTF_STRING_VIEW_H + +#include +#include +#include + +namespace NLMISC { + +/// String view for UTF-8 and UTF-32 iteration as 32-bit codepoints. +/// This string view keeps the string as a reference, it does not make a copy. +/// Only use this for iterating a string's codepoints. +/// Strings are not required to be NUL-terminated, but must have at least one character extra. +class CUtfStringView +{ +public: + inline CUtfStringView() : m_Str(NULL), m_Size(0), m_Iterator(utf32Iterator) {} + + inline CUtfStringView(const char *utf8Str) : m_Str(utf8Str), m_Size(strlen(utf8Str)), m_Iterator(utf8Iterator) {} + inline CUtfStringView(const char *utf8Str, size_t len): m_Str(utf8Str), m_Size(len), m_Iterator(utf8Iterator) + { + nlassert(len <= strlen(utf8Str)); + } +#if defined(NL_OS_WINDOWS) + inline CUtfStringView(const wchar_t *utf16Str) : m_Str(utf16Str), m_Size(wcslen(utf16Str)), m_Iterator(utf16Iterator) {} + inline CUtfStringView(const wchar_t *utf16Str, size_t len): m_Str(utf16Str), m_Size(len), m_Iterator(utf16Iterator) + { + nlassert(len <= wcslen(utf16Str)); + } +#else + inline CUtfStringView(const wchar_t *utf32Str) : m_Str(utf32Str), m_Size(wcslen(utf32Str)), m_Iterator(utf32Iterator) {} + inline CUtfStringView(const wchar_t *utf32Str, size_t len): m_Str(utf32Str), m_Size(len), m_Iterator(utf32Iterator) + { + nlassert(len <= wcslen(utf32Str)); + } +#endif + + inline CUtfStringView(const std::string &utf8Str) : m_Str(utf8Str.c_str()), m_Size(utf8Str.size()), m_Iterator(utf8Iterator) {} + inline CUtfStringView(const ucstring &utf16Str) : m_Str(utf16Str.c_str()), m_Size(utf16Str.size() << 1), m_Iterator(utf16Iterator) {} + inline CUtfStringView(const u32string &utf32Str) : m_Str(utf32Str.c_str()), m_Size(utf32Str.size() << 2), m_Iterator(utf32Iterator) {} + + std::string toUtf8(bool reEncode = false) const; // Makes a copy + ucstring toUtf16(bool reEncode = false) const; // Makes a copy + u32string toUtf32() const; // Makes a copy + + std::wstring toWide() const; // Platform dependent, UTF-16 or UTF-32. Makes a copy. + + inline bool isUtf8() const { return m_Iterator == utf8Iterator; } + inline bool isUtf16() const { return m_Iterator == utf16Iterator; } + inline bool isUtf32() const { return m_Iterator == utf32Iterator; } + + struct const_iterator + { + public: + inline void operator++() + { + m_Char = m_View.m_Iterator(&m_Addr); + if ((ptrdiff_t)m_Addr > ((ptrdiff_t)m_View.m_Str + m_View.m_Size)) + { + m_Addr = 0; + m_Char = 0; + } + } + inline void operator+=(ptrdiff_t a) + { + while (m_Addr) + { + ++(*this); + } + } + inline bool operator!=(const const_iterator &o) const { return m_Addr != o.m_Addr; } + inline bool operator==(const const_iterator &o) const { return m_Addr == o.m_Addr; } + inline const u32char &operator*() const { return m_Char; } + const_iterator() : m_View(*(CUtfStringView *)NULL), m_Addr(NULL), m_Char(0) { } + + const_iterator &operator=(const const_iterator &other) + { + if(this == &other) return *this; + this->~const_iterator(); + return *new(this) const_iterator(other); + } + private: + friend class CUtfStringView; + inline const_iterator(const CUtfStringView &view, const void *addr) : m_View(view), m_Addr(addr), m_Char(addr ? view.m_Iterator(&m_Addr) : 0) { } + const CUtfStringView &m_View; + const void *m_Addr; // Next address + u32char m_Char; + }; + + typedef const_iterator iterator; + + iterator begin() const { return iterator(*this, m_Str); } + inline iterator end() const { return iterator(*this, NULL); } + + /// Largest possible number of characters in this string. + /// Number of actual characters may be less or equal. + inline size_t largestSize() const { return m_Size; } + + inline bool empty() const { return !m_Size; } + const void *ptr() const { return m_Str; } + + inline CUtfStringView substr(const iterator &begin, const iterator &end) const + { + return CUtfStringView(begin.m_Addr, (ptrdiff_t)end.m_Addr - (ptrdiff_t)begin.m_Addr, m_Iterator); + } + + inline bool endsWith(char c) { nlassert(c < 0x80); return *((char *)m_Str + m_Size - 1) == c; } + + CUtfStringView &operator=(const CUtfStringView &other) + { + if(this == &other) return *this; + this->~CUtfStringView(); + return *new(this) CUtfStringView(other); + } + +private: + typedef u32char (*TIterator)(const void **addr); + static u32char utf8Iterator(const void **addr); + static u32char utf16Iterator(const void **addr); + static u32char utf32Iterator(const void **addr); + + inline CUtfStringView(const void *str, size_t len, TIterator it) : m_Str(str), m_Size(len), m_Iterator(it) { } + + const void *const m_Str; // String + const size_t m_Size; // Size in bytes + const TIterator m_Iterator; + +}; /* class CUtfStringView */ + +} /* namespace NLMISC */ + +#endif /* #ifndef NLMISC_STREAMED_PACKAGE_PROVIDER_H */ + +/* end of file */ diff --git a/nel/src/3d/font_generator.cpp b/nel/src/3d/font_generator.cpp index 44d8f5ab0..86a233f22 100644 --- a/nel/src/3d/font_generator.cpp +++ b/nel/src/3d/font_generator.cpp @@ -256,7 +256,7 @@ CFontGenerator::~CFontGenerator () } } -void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &height) +void CFontGenerator::getSizes (u32char c, uint32 size, uint32 &width, uint32 &height) { FT_Error error; @@ -272,7 +272,7 @@ void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &hei if (glyph_index == 0) { // no glyph available, replace with a dot - glyph_index = FT_Get_Char_Index (_Face, ucchar('.')); + glyph_index = FT_Get_Char_Index (_Face, u32char('.')); } // load glyph image into the slot (erase previous one) @@ -294,7 +294,7 @@ void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &hei height = _Face->glyph->metrics.height >> 6; } -uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex) +uint8 *CFontGenerator::getBitmap (u32char c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex) { FT_Error error; @@ -307,11 +307,13 @@ uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool obl // retrieve glyph index from character code FT_UInt glyph_index = FT_Get_Char_Index (_Face, c); + /* if (glyph_index == 0) { // no glyph available, replace with a dot - glyph_index = FT_Get_Char_Index (_Face, ucchar('.')); + glyph_index = FT_Get_Char_Index (_Face, u32char('.')); } + */ // load glyph image into the slot (erase previous one) error = FT_Load_Glyph (_Face, glyph_index, FT_LOAD_DEFAULT); @@ -372,7 +374,7 @@ uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool obl -void CFontGenerator::getKerning (ucchar left, ucchar right, sint32 &kernx) +void CFontGenerator::getKerning (u32char left, u32char right, sint32 &kernx) { if (!FT_HAS_KERNING(_Face)) { @@ -392,14 +394,14 @@ void CFontGenerator::getKerning (ucchar left, ucchar right, sint32 &kernx) -uint32 CFontGenerator::getCharIndex (ucchar c) +uint32 CFontGenerator::getCharIndex (u32char c) { uint32 ret = FT_Get_Char_Index(_Face, c); if (ret == 0) { // no glyph available, replace with a dot - ret = FT_Get_Char_Index (_Face, ucchar('.')); + ret = FT_Get_Char_Index (_Face, u32char('.')); } return ret; @@ -473,14 +475,14 @@ CFontGenerator::~CFontGenerator () DeleteDC (hdcDib); } -void CFontGenerator::getSizes (ucchar c, uint32 size, uint32 &width, uint32 &height) +void CFontGenerator::getSizes (u32char c, uint32 size, uint32 &width, uint32 &height) { } HFONT hFont = NULL; uint32 CurrentFontSize = 0; -uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex) +uint8 *CFontGenerator::getBitmap (u32char c, uint32 size, bool embolden, bool oblique, uint32 &width, uint32 &height, uint32 &pitch, sint32 &left, sint32 &top, sint32 &advx, uint32 &glyphIndex) { if (size == 0) { @@ -527,7 +529,7 @@ uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool obl SelectObject (hdcDib, hFont); SelectObject (hdcDib, Dib); - const ucchar cc = /*(char)*/ c; + const u32char cc = /*(char)*/ c; // prevent outputing white glyph if char is not available in font DWORD glyphIndex; @@ -637,13 +639,13 @@ uint8 *CFontGenerator::getBitmap (ucchar c, uint32 size, bool embolden, bool obl -void CFontGenerator::getKerning (ucchar left, ucchar right, sint32 &kernx) +void CFontGenerator::getKerning (u32char left, u32char right, sint32 &kernx) { } -uint32 CFontGenerator::getCharIndex (ucchar c) +uint32 CFontGenerator::getCharIndex (u32char c) { return 0; } diff --git a/nel/src/3d/font_manager.cpp b/nel/src/3d/font_manager.cpp index d00ebb8f5..70fb59639 100644 --- a/nel/src/3d/font_manager.cpp +++ b/nel/src/3d/font_manager.cpp @@ -63,27 +63,8 @@ CMaterial* CFontManager::getFontMaterial() return _MatFont; } - -// *************************************************************************** -void CFontManager::computeString (const std::string &s, - CFontGenerator *fontGen, - const NLMISC::CRGBA &color, - uint32 fontSize, - bool embolden, - bool oblique, - IDriver *driver, - CComputedString &output, - bool keep800x600Ratio) -{ - // static to avoid reallocation - static ucstring ucs; - ucs= s; - computeString(ucs, fontGen, color, fontSize, embolden, oblique, driver, output, keep800x600Ratio); -} - - // *************************************************************************** -void CFontManager::computeString (const ucstring &s, +void CFontManager::computeString (NLMISC::CUtfStringView sv, CFontGenerator *fontGen, const NLMISC::CRGBA &color, uint32 fontSize, @@ -109,7 +90,7 @@ void CFontManager::computeString (const ucstring &s, } // Setting vertices format - output.Vertices.setNumVertices (4 * (uint32)s.size()); + output.Vertices.setNumVertices (4 * (uint32)sv.largestSize()); // 1 character <-> 1 quad sint32 penx = 0, dx; @@ -144,7 +125,8 @@ void CFontManager::computeString (const ucstring &s, output.StringHeight = 0; // save string info for later rebuild as needed - output.Text = s; + if (sv.ptr() != output.Text.c_str()) // don't resave if rebuilding + output.Text = sv.toUtf8(); output.CacheVersion = getCacheVersion(); uint j = 0; @@ -156,10 +138,11 @@ void CFontManager::computeString (const ucstring &s, hlfPixScrH = 0.f; // For all chars - for (uint i = 0; i < s.size(); i++) + //for (uint i = 0; i < s.size(); i++) + for (NLMISC::CUtfStringView::iterator it(sv.begin()), end(sv.end()); it != end; ++it) { // Creating font - k.Char = s[i]; + k.Char = *it; k.FontGenerator = fontGen; k.Size = fontSize; k.Embolden = embolden; @@ -245,7 +228,23 @@ void CFontManager::computeString (const ucstring &s, // *************************************************************************** -void CFontManager::computeStringInfo ( const ucstring &s, +void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv, + CFontGenerator *fontGen, + const NLMISC::CRGBA &color, + uint32 fontSize, + bool embolden, + bool oblique, + IDriver *driver, + CComputedString &output, + bool keep800x600Ratio ) +{ + computeStringInfo(sv, sv.largestSize(), fontGen, color, fontSize, embolden, oblique, driver, output, keep800x600Ratio); +} + + +// *************************************************************************** +void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv, + size_t len, CFontGenerator *fontGen, const NLMISC::CRGBA &color, uint32 fontSize, @@ -258,10 +257,11 @@ void CFontManager::computeStringInfo ( const ucstring &s, output.Color = color; // save string info for later rebuild as needed - output.Text = s; + if (sv.ptr() != output.Text.c_str()) // don't resave if rebuilding + output.Text = sv.toUtf8(); output.CacheVersion = 0; - if (s.empty()) + if (sv.empty()) { output.StringWidth = 0.f; output.StringHeight = 0; @@ -290,10 +290,11 @@ void CFontManager::computeStringInfo ( const ucstring &s, CTextureFont::SLetterKey k; CTextureFont::SLetterInfo *pLI; - for (uint i = 0; i < s.size(); i++) + size_t idx = 0; + for (NLMISC::CUtfStringView::iterator it(sv.begin()), end(sv.end()); it != end && idx < len; ++it, ++idx) { // Creating font - k.Char = s[i]; + k.Char = *it; k.FontGenerator = fontGen; k.Size = fontSize; k.Embolden = embolden; diff --git a/nel/src/3d/text_context.cpp b/nel/src/3d/text_context.cpp index 1ccb920e4..ba40904b3 100644 --- a/nel/src/3d/text_context.cpp +++ b/nel/src/3d/text_context.cpp @@ -77,13 +77,11 @@ uint32 CTextContext::textPush (const char *format, ...) char *str; NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize); - ucstring uc; - uc.fromUtf8((const char *)str); - return textPush(uc); + return textPush(str); } // ------------------------------------------------------------------------------------------------ -uint32 CTextContext::textPush (const ucstring &str) +uint32 CTextContext::textPush (NLMISC::CUtfStringView sv) { nlassert(_FontGen); @@ -103,7 +101,7 @@ uint32 CTextContext::textPush (const ucstring &str) nlassert (index < _CacheStrings.size()); CComputedString &strToFill = _CacheStrings[index]; - _FontManager->computeString (str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); + _FontManager->computeString (sv, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); // just compute letters, glyphs are rendered on demand before first draw //_FontManager->computeStringInfo(str, _FontGen, _Color, _FontSize, _Embolden, _Oblique, _Driver, strToFill, _Keep800x600Ratio); diff --git a/nel/src/3d/text_context_user.cpp b/nel/src/3d/text_context_user.cpp index 0430eae1a..95d9ebe1c 100644 --- a/nel/src/3d/text_context_user.cpp +++ b/nel/src/3d/text_context_user.cpp @@ -231,11 +231,11 @@ uint32 CTextContextUser::textPush(const char *format, ...) return _TextContext.textPush(ucstring(str)) ; } -uint32 CTextContextUser::textPush(const ucstring &str) +uint32 CTextContextUser::textPush(NLMISC::CUtfStringView sv) { H_AUTO2; - return _TextContext.textPush(str) ; + return _TextContext.textPush(sv) ; } void CTextContextUser::setStringColor(uint32 i, CRGBA newCol) { @@ -279,11 +279,18 @@ UTextContext::CStringInfo CTextContextUser::getStringInfo(uint32 i) else return CStringInfo(cstr->StringWidth, cstr->StringHeight, cstr->StringLine); } -UTextContext::CStringInfo CTextContextUser::getStringInfo(const ucstring &str) +UTextContext::CStringInfo CTextContextUser::getStringInfo(NLMISC::CUtfStringView sv) { H_AUTO2; - _TextContext.computeStringInfo(str, _CacheString); + _TextContext.computeStringInfo(sv, _CacheString); + return CStringInfo (_CacheString.StringWidth, _CacheString.StringHeight, _CacheString.StringLine); +} +UTextContext::CStringInfo CTextContextUser::getStringInfo(NLMISC::CUtfStringView sv, size_t len) +{ + H_AUTO2; + + _TextContext.computeStringInfo(sv, _CacheString, len); return CStringInfo (_CacheString.StringWidth, _CacheString.StringHeight, _CacheString.StringLine); } void CTextContextUser::clear() @@ -319,11 +326,11 @@ void CTextContextUser::printClipAtOld (float x, float y, uint32 i, float xmin, f printClipAt(rdrBuffer, x, y ,i, xmin, ymin, xmax, ymax); flushRenderBuffer(&rdrBuffer); } -void CTextContextUser::printAt(float x, float y, const ucstring &ucstr) +void CTextContextUser::printAt(float x, float y, NLMISC::CUtfStringView sv) { H_AUTO2; - _TextContext.printAt(x, y, ucstr); + _TextContext.printAt(x, y, sv); _DriverUser->restoreMatrixContext(); } void CTextContextUser::printfAt(float x, float y, const char * format, ...) @@ -337,12 +344,12 @@ void CTextContextUser::printfAt(float x, float y, const char * format, ...) _DriverUser->restoreMatrixContext(); } -void CTextContextUser::render3D(const CMatrix &mat, const ucstring &ucstr) +void CTextContextUser::render3D(const CMatrix &mat, NLMISC::CUtfStringView sv) { NL3D_HAUTO_RENDER_3D_TEXTCONTEXT; CComputedString computedStr; - _TextContext.computeString(ucstr,computedStr); + _TextContext.computeString(sv,computedStr); computedStr.render3D(*_Driver,mat); @@ -355,7 +362,7 @@ void CTextContextUser::render3D(const CMatrix &mat, const char *format, ...) char *str; NLMISC_CONVERT_VARGS (str, format, NLMISC::MaxCStringSize); - render3D(mat, ucstring(str)); + render3D(mat, str); _DriverUser->restoreMatrixContext(); } diff --git a/nel/src/gui/group_editbox.cpp b/nel/src/gui/group_editbox.cpp index 2879a62af..b9dc44895 100644 --- a/nel/src/gui/group_editbox.cpp +++ b/nel/src/gui/group_editbox.cpp @@ -21,6 +21,7 @@ #include "stdpch.h" #include "nel/gui/group_editbox.h" #include "nel/misc/command.h" +#include "nel/misc/utf_string_view.h" #include "nel/gui/view_text.h" #include "nel/misc/xml_auto_ptr.h" #include "nel/gui/interface_options.h" @@ -826,11 +827,12 @@ namespace NLGUI } // ---------------------------------------------------------------------------- - void CGroupEditBox::writeString(const ucstring &str, bool replace, bool atEnd) + void CGroupEditBox::writeString(const ucstring &str16, bool replace, bool atEnd) { + u32string str = CUtfStringView(str16).toUtf32(); sint length = (sint)str.length(); - ucstring toAppend; + u32string toAppend; // filter character depending on the entry type switch (_EntryType) { @@ -963,7 +965,7 @@ namespace NLGUI { length = _MaxNumChar - (sint)_InputString.length(); } - ucstring toAdd = toAppend.substr(0, length); + u32string toAdd = toAppend.substr(0, length); sint32 minPos; sint32 maxPos; if (_CurrSelection == this) @@ -1013,7 +1015,7 @@ namespace NLGUI _CursorAtPreviousLineEnd = false; if (_ClearOnEscape) { - setInputString(ucstring("")); + setInputString(u32string()); triggerOnChangeAH(); } CWidgetManager::getInstance()->setCaptureKeyboard(NULL); @@ -1059,8 +1061,9 @@ namespace NLGUI { if (isKeyRETURN) { - ucstring copyStr= _InputString; - if ((uint) std::count(copyStr.begin(), copyStr.end(), '\n') >= _MaxNumReturn) + //ucstring copyStr= _InputString; + //if ((uint) std::count(copyStr.begin(), copyStr.end(), '\n') >= _MaxNumReturn) + if ((uint)std::count(_InputString.begin(), _InputString.end(), '\n') >= _MaxNumReturn) break; } @@ -1121,11 +1124,11 @@ namespace NLGUI if(_EntryType==Integer && (_IntegerMinValue!=INT_MIN || _IntegerMaxValue!=INT_MAX)) { // estimate new string - ucstring copyStr= _InputString; - ucstring::iterator it = copyStr.begin() + _CursorPos; + u32string copyStr= _InputString; + u32string::iterator it = copyStr.begin() + _CursorPos; copyStr.insert(it, c); sint32 value; - fromString(copyStr.toString(), value); + fromString(CUtfStringView(copyStr).toUtf8(), value); // if out of bounds, abort char if(value<_IntegerMinValue || value>_IntegerMaxValue) return; @@ -1134,12 +1137,12 @@ namespace NLGUI if(_EntryType==PositiveInteger && (_PositiveIntegerMinValue!=0 || _PositiveIntegerMaxValue!=UINT_MAX)) { // estimate new string - ucstring copyStr= _InputString; - ucstring::iterator it = copyStr.begin() + _CursorPos; + u32string copyStr= _InputString; + u32string::iterator it = copyStr.begin() + _CursorPos; copyStr.insert(it, c); // \todo yoyo: this doesn't really work i think.... uint32 value; - fromString(copyStr.toString(), value); + fromString(CUtfStringView(copyStr).toUtf8(), value); // if out of bounds, abort char if(value<_PositiveIntegerMinValue || value>_PositiveIntegerMaxValue) return; @@ -1148,7 +1151,7 @@ namespace NLGUI if ((uint) _InputString.length() < _MaxNumChar) { makeTopWindow(); - ucstring::iterator it = _InputString.begin() + _CursorPos; + u32string::iterator it = _InputString.begin() + _CursorPos; _InputString.insert(it, c); ++ _CursorPos; triggerOnChangeAH(); @@ -1229,11 +1232,11 @@ namespace NLGUI { makeTopWindow(); // for french, deutsch and russian, be aware of unicode - std::string command = _InputString.substr(1).toUtf8(); + std::string command = CUtfStringView(_InputString.substr(1)).toUtf8(); ICommand::expand(command); - // then back to ucstring - _InputString.fromUtf8(command); - _InputString = '/' + _InputString; + // then back to u32string + _InputString = CUtfStringView('/' + command).toUtf32(); + _InputString = _InputString; _CursorPos = (sint32)_InputString.length(); _CursorAtPreviousLineEnd = false; triggerOnChangeAH(); @@ -1260,7 +1263,7 @@ namespace NLGUI // else delete last character else if(_InputString.size () > 0 && _CursorPos != 0) { - ucstring::iterator it = _InputString.begin() + (_CursorPos - 1); + u32string::iterator it = _InputString.begin() + (_CursorPos - 1); _InputString.erase(it); -- _CursorPos; _CursorAtPreviousLineEnd = false; @@ -1439,7 +1442,7 @@ namespace NLGUI } else { - usTmp = _Prompt + _InputString; + usTmp = _Prompt + CUtfStringView(_InputString).toUtf16(); } _ViewText->setText (usTmp); } @@ -1622,7 +1625,7 @@ namespace NLGUI // ---------------------------------------------------------------------------- - void CGroupEditBox::setInputString(const ucstring &str) + void CGroupEditBox::setInputString(const u32string &str) { _InputString = str; if (_CursorPos > (sint32) str.length()) @@ -1641,7 +1644,7 @@ namespace NLGUI void CGroupEditBox::setDefaultInputString(const ucstring &str) { _DefaultInputString= true; - setInputString(str); + setInputString(CUtfStringView(str).toUtf32()); } @@ -1649,35 +1652,35 @@ namespace NLGUI sint32 CGroupEditBox::getInputStringAsInt() const { sint32 value; - fromString(_InputString.toString(), value); + fromString(getInputStringAsUtf8(), value); return value; } // *************************************************************************** void CGroupEditBox::setInputStringAsInt(sint32 val) { - setInputString(NLMISC::toString(val)); + setInputStringAsUtf8(NLMISC::toString(val)); } // *************************************************************************** sint64 CGroupEditBox::getInputStringAsInt64() const { sint64 value; - fromString(_InputString.toString(), value); + fromString(getInputStringAsUtf8(), value); return value; } // *************************************************************************** void CGroupEditBox::setInputStringAsInt64(sint64 val) { - setInputString(NLMISC::toString(val)); + setInputStringAsUtf8(NLMISC::toString(val)); } // *************************************************************************** float CGroupEditBox::getInputStringAsFloat() const { float value; - fromString(_InputString.toString(), value); + fromString(getInputStringAsUtf8(), value); return value; } @@ -1685,14 +1688,14 @@ namespace NLGUI void CGroupEditBox::setInputStringAsFloat(float val) { string fmt= "%." + NLMISC::toString(_MaxFloatPrec) + "f"; - setInputString(NLMISC::toString(fmt.c_str(), val)); + setInputStringAsUtf8(NLMISC::toString(fmt.c_str(), val)); } // *************************************************************************** void CGroupEditBox::cutSelection() { - sint32 minPos= min(_CursorPos, _SelectCursorPos); - sint32 maxPos= max(_CursorPos, _SelectCursorPos); + ptrdiff_t minPos= min(_CursorPos, _SelectCursorPos); + ptrdiff_t maxPos= max(_CursorPos, _SelectCursorPos); // cut the selection if(!_InputString.empty()) { @@ -1706,10 +1709,10 @@ namespace NLGUI // *************************************************************************** ucstring CGroupEditBox::getSelection() { - sint32 minPos= min(_CursorPos, _SelectCursorPos); - sint32 maxPos= max(_CursorPos, _SelectCursorPos); + ptrdiff_t minPos= min(_CursorPos, _SelectCursorPos); + ptrdiff_t maxPos= max(_CursorPos, _SelectCursorPos); // get the selection - return _InputString.substr(minPos, maxPos-minPos); + return CUtfStringView(_InputString.substr(minPos, maxPos-minPos)).toUtf16(); } @@ -1738,13 +1741,25 @@ namespace NLGUI // *************************************************************************** void CGroupEditBox::setInputStringAsUtf8(const std::string &str) { - setInputString(ucstring::makeFromUtf8(str)); + setInputString(CUtfStringView(str).toUtf32()); } // *************************************************************************** std::string CGroupEditBox::getInputStringAsUtf8() const { - return _InputString.toUtf8(); + return CUtfStringView(_InputString).toUtf8(); + } + + // *************************************************************************** + void CGroupEditBox::setInputStringAsUtf16(const ucstring &str) + { + setInputString(CUtfStringView(str).toUtf32()); + } + + // *************************************************************************** + ucstring CGroupEditBox::getInputStringAsUtf16() const + { + return CUtfStringView(_InputString).toUtf16(); } // *************************************************************************** @@ -1755,7 +1770,7 @@ namespace NLGUI return; // set the string and maybe execute - setInputString((ucchar) '/' + command); + setInputString(CUtfStringView((ucchar) '/' + command).toUtf32()); if (execute) { // stop selection @@ -1810,13 +1825,30 @@ namespace NLGUI // *************************************************************************** void CGroupEditBox::serialConfig(NLMISC::IStream &f) { - f.serialVersion(0); + uint version = f.serialVersion(1); if(_DefaultInputString) // Don't want to save the default input { _DefaultInputString= false; _InputString.clear(); } - f.serial(_InputString); + if (version < 1) + { + ucstring str; + if (!f.isReading()) + str = CUtfStringView(_InputString).toUtf16(); + f.serial(str); + if (f.isReading()) + _InputString = CUtfStringView(str).toUtf32(); + } + else + { + std::string str; + if (!f.isReading()) + str = CUtfStringView(_InputString).toUtf8(); + f.serial(str); + if (f.isReading()) + _InputString = CUtfStringView(str).toUtf32(); + } f.serial(_CursorPos); f.serial(_PrevNumLine); if (f.isReading()) @@ -1838,7 +1870,7 @@ namespace NLGUI void CGroupEditBox::onQuit() { // clear the text and restore backup pos before final save - setInputString(ucstring("")); + setInputString(u32string()); _CurrSelection = NULL; } @@ -1846,7 +1878,7 @@ namespace NLGUI void CGroupEditBox::onLoadConfig() { // config is not saved when there's an empty string, so restore that default state. - setInputString(ucstring("")); + setInputString(u32string()); _CurrSelection = NULL; _PrevNumLine = 1; } @@ -1861,7 +1893,7 @@ namespace NLGUI if (_DefaultInputString) { _DefaultInputString= false; - setInputString(ucstring()); + setInputString(u32string()); } _CanRedo = false; _CanUndo = false; diff --git a/nel/src/gui/group_html.cpp b/nel/src/gui/group_html.cpp index 0c294c766..7f80405ce 100644 --- a/nel/src/gui/group_html.cpp +++ b/nel/src/gui/group_html.cpp @@ -27,6 +27,7 @@ #include "nel/misc/types_nl.h" #include "nel/misc/rgba.h" #include "nel/misc/algo.h" +#include "nel/misc/utf_string_view.h" #include "nel/gui/libwww.h" #include "nel/gui/group_html.h" #include "nel/gui/group_list.h" @@ -3023,7 +3024,7 @@ namespace NLGUI CGroupEditBox *eb = dynamic_cast(textArea->getGroup("eb")); if (eb) { - eb->setInputString(decodeHTMLEntities(content)); + eb->setInputString(CUtfStringView(decodeHTMLEntities(content)).toUtf32()); if (style.hasStyle("background-color")) { CViewBitmap *bg = dynamic_cast(eb->getView("bg")); diff --git a/nel/src/gui/view_text.cpp b/nel/src/gui/view_text.cpp index cf8dca87f..73e88d4f4 100644 --- a/nel/src/gui/view_text.cpp +++ b/nel/src/gui/view_text.cpp @@ -2463,9 +2463,8 @@ namespace NLGUI if ((uint) (index - charIndex) > currWord.NumSpaces) { // get the x position - ucstring subStr = currWord.Text.substr(0, index - charIndex - currWord.NumSpaces); // compute the size - UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); + UTextContext::CStringInfo si = TextContext->getStringInfo(currWord.Text, (ptrdiff_t)index - charIndex - currWord.NumSpaces); fx = px + si.StringWidth + currWord.NumSpaces * currLine.getSpaceWidth(); x = fx / _Scale; @@ -2493,9 +2492,8 @@ namespace NLGUI else { // get the x position - ucstring subStr = _Text.substr(0, index); // compute the size - UTextContext::CStringInfo si = TextContext->getStringInfo(subStr); + UTextContext::CStringInfo si = TextContext->getStringInfo(_Text, index); y = 0; x = (sint) ceilf(si.StringWidth / _Scale); } @@ -2508,12 +2506,13 @@ namespace NLGUI float px = 0.f; UTextContext::CStringInfo si; - ucstring singleChar(" "); - uint i; - for (i = 0; i < textValue.length(); ++i) + u32string singleChar(1, ' '); + uint i = 0; + NLMISC::CUtfStringView sv(textValue); + for (NLMISC::CUtfStringView::iterator it(sv.begin()), end(sv.end()); it != end; ++it, ++i) { // get character width - singleChar[0] = textValue[i]; + singleChar[0] = *it; si = textContext.getStringInfo(singleChar); px += si.StringWidth; // the character is at the i - 1 position diff --git a/nel/src/misc/path.cpp b/nel/src/misc/path.cpp index a2f817210..2e3aacae6 100644 --- a/nel/src/misc/path.cpp +++ b/nel/src/misc/path.cpp @@ -2790,16 +2790,13 @@ bool CPath::isAbsolutePath(const std::string &path) bool CFile::setRWAccess(const std::string &filename) { #ifdef NL_OS_WINDOWS - ucstring ucFile; - ucFile.fromUtf8(filename); - - wchar_t *wideFile = (wchar_t*)ucFile.c_str(); + std::wstring wideFile = NLMISC::utf8ToWide(filename); // if the file exists and there's no write access - if (_waccess (wideFile, 00) == 0 && _waccess (wideFile, 06) == -1) + if (_waccess (wideFile.c_str(), 00) == 0 && _waccess (wideFile.c_str(), 06) == -1) { // try to set the read/write access - if (_wchmod (wideFile, _S_IREAD | _S_IWRITE) == -1) + if (_wchmod (wideFile.c_str(), _S_IREAD | _S_IWRITE) == -1) { if (INelContext::getInstance().getAlreadyCreateSharedAmongThreads()) { @@ -2822,6 +2819,7 @@ bool CFile::setRWAccess(const std::string &filename) return false; } } +#endif else { if (INelContext::getInstance().getAlreadyCreateSharedAmongThreads()) @@ -2830,7 +2828,6 @@ bool CFile::setRWAccess(const std::string &filename) } // return false; } -#endif return true; } diff --git a/nel/src/misc/string_common.cpp b/nel/src/misc/string_common.cpp index 93122cc70..f869a5d35 100644 --- a/nel/src/misc/string_common.cpp +++ b/nel/src/misc/string_common.cpp @@ -21,6 +21,7 @@ #include "nel/misc/string_common.h" #include "nel/misc/sstring.h" +#include "nel/misc/utf_string_view.h" using namespace std; @@ -228,8 +229,7 @@ std::string wideToUtf8(const wchar_t *str, size_t len) #if defined(NL_OS_WINDOWS) return winWideToCp(str, len, CP_UTF8); #else - // TODO: UTF-32 to UTF-8 - nlassert(false); + return CUtfStringView(str, len).toUtf8(); #endif } @@ -242,10 +242,9 @@ std::string wideToUtf8(const std::wstring &str) std::wstring utf8ToWide(const char *str, size_t len) { #if defined(NL_OS_WINDOWS) - return winCpToWide(str, len, CP_UTF8); + return winCpToWide(str, len, CP_UTF8); // UTF-16 #else - // TODO: UTF-8 to UTF-32 - nlassert(false); + return CUtfStringView(str, len).toWide(); // UTF-32 #endif } diff --git a/nel/src/misc/system_utils.cpp b/nel/src/misc/system_utils.cpp index 42fe63fca..63eecbf0d 100644 --- a/nel/src/misc/system_utils.cpp +++ b/nel/src/misc/system_utils.cpp @@ -168,7 +168,7 @@ bool CSystemUtils::copyTextToClipboard(const ucstring &text) // allocates a buffer to copy text in global memory std::string textLocal; - if (!isUnicode) textLocal = NLMISC::wideToMbcs(text); + if (!isUnicode) textLocal = NLMISC::wideToMbcs((const wchar_t *)text.c_str(), text.size()); if (text.size() && !textLocal.size()) textLocal = text.toString(); HGLOBAL mem = GlobalAlloc(GHND | GMEM_DDESHARE, isUnicode ? ((text.size() + 1) * sizeof(wchar_t)) : textLocal.size()); @@ -232,7 +232,7 @@ bool CSystemUtils::pasteTextFromClipboard(ucstring &text) } else { - static_cast(text) = NLMISC::mbcsToWide((const char *)hLock); + reinterpret_cast(text) = NLMISC::mbcsToWide((const char *)hLock); if (!text.size() && ((const char *)hLock)[0]) text = (const char *)hLock; } diff --git a/nel/src/misc/ucstring.cpp b/nel/src/misc/ucstring.cpp index 5fad643ce..79cf78f7e 100644 --- a/nel/src/misc/ucstring.cpp +++ b/nel/src/misc/ucstring.cpp @@ -16,6 +16,7 @@ #include "stdmisc.h" #include "nel/misc/ucstring.h" +#include "nel/misc/utf_string_view.h" void ucstring::toString(std::string &str) const { @@ -31,138 +32,12 @@ void ucstring::toString(std::string &str) const std::string ucstring::toUtf8() const { -#if defined(NL_OS_WINDOWS) - // Use OS implementation - nlctassert(sizeof(wchar_t) == sizeof(ucchar)); - nlctassert(sizeof(wchar_t) == sizeof(uint16)); - return NLMISC::wideToUtf8(static_cast(*this)); -#else - std::string res; - ucstring::const_iterator first(begin()), last(end()); - for (; first != last; ++first) - { - //ucchar c = *first; - uint nbLoop = 0; - if (*first < 0x80) - res += char(*first); - else if (*first < 0x800) - { - ucchar c = *first; - c = c >> 6; - c = c & 0x1F; - res += char(c) | 0xC0; - nbLoop = 1; - } - else /*if (*first < 0x10000)*/ - { - ucchar c = *first; - c = c >> 12; - c = c & 0x0F; - res += char(c) | 0xE0; - nbLoop = 2; - } - - for (uint i = 0; i < nbLoop; ++i) - { - ucchar c = *first; - c = c >> ((nbLoop - i - 1) * 6); - c = c & 0x3F; - res += char(c) | 0x80; - } - } - return res; -#endif + return NLMISC::CUtfStringView(*this).toUtf8(); } void ucstring::fromUtf8(const std::string &stringUtf8) { -#if defined(NL_OS_WINDOWS) - // Use OS implementation - nlctassert(sizeof(wchar_t) == sizeof(ucchar)); - nlctassert(sizeof(wchar_t) == sizeof(uint16)); - nlctassert(sizeof(std::wstring) == sizeof(ucstring)); // These can be swapped on Windows - static_cast(*this) = nlmove(NLMISC::utf8ToWide(stringUtf8)); - if (stringUtf8.size() && !size()) - rawCopy(stringUtf8); -#else - // clear the string - erase(); - - uint8 c; - ucchar code; - sint iterations = 0; - - std::string::const_iterator first(stringUtf8.begin()), last(stringUtf8.end()); - for (; first != last;) - { - c = *first++; - code = c; - - if ((code & 0xFE) == 0xFC) - { - code &= 0x01; - iterations = 5; - } - else if ((code & 0xFC) == 0xF8) - { - code &= 0x03; - iterations = 4; - } - else if ((code & 0xF8) == 0xF0) - { - code &= 0x07; - iterations = 3; - } - else if ((code & 0xF0) == 0xE0) - { - code &= 0x0F; - iterations = 2; - } - else if ((code & 0xE0) == 0xC0) - { - code &= 0x1F; - iterations = 1; - } - else if ((code & 0x80) == 0x80) - { - // If it's not a valid UTF8 string, just copy the line without utf8 conversion - rawCopy(stringUtf8); - return; - } - else - { - push_back(code); - iterations = 0; - } - - if (iterations) - { - for (sint i = 0; i < iterations; i++) - { - if (first == last) - { - // If it's not a valid UTF8 string, just copy the line without utf8 conversion - rawCopy(stringUtf8); - return; - } - - uint8 ch; - ch = *first++; - - if ((ch & 0xC0) != 0x80) - { - // If it's not a valid UTF8 string, just copy the line without utf8 conversion - rawCopy(stringUtf8); - return; - } - - code <<= 6; - code |= (ucchar)(ch & 0x3F); - } - push_back(code); - } - } -#endif + *this = NLMISC::CUtfStringView(stringUtf8).toUtf16(); } void ucstring::rawCopy(const std::string &str) diff --git a/nel/src/misc/utf_string_view.cpp b/nel/src/misc/utf_string_view.cpp new file mode 100644 index 000000000..db2ea7cec --- /dev/null +++ b/nel/src/misc/utf_string_view.cpp @@ -0,0 +1,235 @@ +// NeL - MMORPG Framework +// Copyright (C) 2020 Jan BOON (Kaetemi) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdmisc.h" + +// Project includes +#include + +// References: +// - https://twiserandom.com/unicode/unicode-encoding-utf-8-utf-16-utf-32/ +// - https://www.compart.com/en/unicode/U+1F30D +// - 0xF0 0x9F 0x8C 0x8D +// - 0xD83C 0xDF0D +// - 0x0001F30D + +namespace NLMISC +{ + +std::string CUtfStringView::toUtf8(bool reEncode) const +{ + // Decode UTF and encode UTF-8 + // This implementation makes no attempt at fixing invalid codepoints + if (m_Iterator == utf8Iterator && !reEncode) + return std::string((const char *)m_Str, (const char *)((ptrdiff_t)m_Str + m_Size)); + std::string res; + res.reserve(m_Size); + for (iterator it(begin()), end(end()); it != end; ++it) + { + u32char c = *it; + if (c < 0x80) + { + // Encode as 1 byte + res += (char)c; + } + else if (c < 0x0800) + { + // Encode as 2 bytes + res += (char)((c & 0x07C0) >> 6) | 0xC0; + res += (char)(c & 0x3F) | 0x80; + } + else if (c < 0x010000) + { + // Encode as 3 bytes + res += (char)((c & 0xF000) >> 12) | 0xE0; + res += (char)((c & 0x0FC0) >> 6) | 0x80; + res += (char)(c & 0x3F) | 0x80; + } + else + { + // Encode as 4 bytes + res += (char)((c & 0x1C0000) >> 18) | 0xF0; + res += (char)((c & 0x03F000) >> 12) | 0x80; + res += (char)((c & 0x0FC0) >> 6) | 0x80; + res += (char)(c & 0x3F) | 0x80; + } + } + return res; +} + +ucstring CUtfStringView::toUtf16(bool reEncode) const +{ + if (m_Iterator == utf16Iterator && !reEncode) + return ucstring((const ucchar *)m_Str, (const ucchar *)((ptrdiff_t)m_Str + m_Size)); + ucstring res; + res.reserve(m_Size << 1); + for (iterator it(begin()), end(end()); it != end; ++it) + { + u32char c = *it; + if (c < 0x10000) + { + res += c; + } + else + { + c -= 0x10000; + res += (c >> 10) | 0xD800; + res += (c & 0x3FF) | 0xDC00; + } + } + return res; +} + +u32string CUtfStringView::toUtf32() const +{ + // Decode any UTF + // This implementation makes no attempt at fixing bad encoding + if (m_Iterator == utf32Iterator) + return u32string((const u32char *)m_Str, (const u32char *)((ptrdiff_t)m_Str + m_Size)); + u32string res; + res.reserve(m_Size << 2); + for (iterator it(begin()), end(end()); it != end; ++it) + res += *it; + return res; +} + +std::wstring CUtfStringView::toWide() const +{ +#ifdef NL_OS_WINDOWS + if (m_Iterator == utf16Iterator) + return std::wstring((const wchar_t *)m_Str, (const wchar_t *)((ptrdiff_t)m_Str + m_Size)); + std::wstring res; + res.reserve(m_Size << 1); + for (iterator it(begin()), end(end()); it != end; ++it) + { + u32char c = *it; + if (c < 0x10000) + { + res += c; + } + else + { + c -= 0x10000; + res += (c >> 10) | 0xD800; + res += (c & 0x3FF) | 0xDC00; + } + } + return res; +#else + if (m_Iterator == utf32Iterator) + return std::wstring((const wchar_t *)m_Str, (const wchar_t *)((ptrdiff_t)m_Str + m_Size)); + std::wstring res; + res.reserve(m_Size << 2); + for (iterator it(begin()), end(end()); it != end; ++it) + res += *it; + return res; +#endif +} + +u32char CUtfStringView::utf8Iterator(const void **addr) +{ + // Decode UTF-8 + // This implementation makes no attempt at fixing bad encoding, except for bad UTF-16 surrogate pairs + const uint8 **pp = reinterpret_cast(addr); + u32char c0 = **pp; + ++(*pp); + if ((c0 & 0xC0) == 0xC0) + { + uint8 cx = **pp; + if ((cx & 0xC0) == 0x80) + { + ++(*pp); + c0 &= 0x3F; // Drop first two bits + c0 <<= 6; + c0 |= (cx & 0x3F); // 12 bits now (6 + 6), 2-byte encoding + if (c0 & 0x800) + { + cx = **pp; + if ((cx & 0xC0) == 0x80) + { + ++(*pp); + c0 &= 0x07FF; // Drop first bit + c0 <<= 6; + c0 |= (cx & 0x3F); // 17 bits now (12 - 1 + 6), 3-byte encoding + if (c0 & 0x10000) + { + cx = **pp; + if ((cx & 0xC0) == 0x80) + { + ++(*pp); + c0 &= 0xFFFF; // Drop first bit + c0 <<= 6; + c0 |= (cx & 0x3F); // 22 bits now (17 - 1 + 6), 3-byte encoding + } + } + else if ((c0 & 0xFC00) == 0xD800) // Higher bits of nutcase UTF-16 encoded as UTF-8 + { + uint8 cy; + if ((*pp)[0] == 0xED && ((cx = (*pp)[1]) & 0xF0) == 0xB0 && ((cy = (*pp)[2]) & 0xC0) == 0x80) + { + // Lower bits of nutcase UTF-16 encoded as UTF-8 + (*pp) += 3; + uint16 c1 = (cx & 0x0F); + c1 <<= 6; + c1 |= (cy & 0x3F); + c0 &= 0x03FF; + c0 <<= 10; + c0 |= (c1 & 0x03FF); + c0 += 0x10000; + } + } + } + } + } + } + return c0; +} + +u32char CUtfStringView::utf16Iterator(const void **addr) +{ + // Decode UTF-16 + // This implementation makes no attempt at fixing bad encoding + const uint16 **pp = reinterpret_cast(addr); + u32char c0 = **pp; + ++(*pp); + if ((c0 & 0xFC00) == 0xD800) // Higher bits + { + uint16 c1 = **pp; + if ((c1 & 0xFC00) == 0xDC00) // Lower bits + { + ++(*pp); + c0 &= 0x03FF; + c0 <<= 10; + c0 |= (c1 & 0x03FF); + c0 += 0x10000; + } + } + return c0; +} + +u32char CUtfStringView::utf32Iterator(const void **addr) +{ + // UTF-32 + // This implementation makes no attempt at fixing bad encoding + const u32char **pp = reinterpret_cast(addr); + u32char c = **pp; + ++(*pp); + return c; +} + +} /* namespace NLMISC */ + +/* end of file */ diff --git a/ryzom/client/src/connection.cpp b/ryzom/client/src/connection.cpp index c5f74f22e..a4da83f48 100644 --- a/ryzom/client/src/connection.cpp +++ b/ryzom/client/src/connection.cpp @@ -1684,7 +1684,7 @@ public: ucstring sSurName = ucstring("NotSet"); CGroupEditBox *pGEB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(sEditBoxPath)); if (pGEB != NULL) - sFirstName = pGEB->getInputString(); + sFirstName = pGEB->getInputStringAsUtf16(); else nlwarning ("can't get edit box name : %s",sEditBoxPath.c_str()); @@ -2560,7 +2560,7 @@ static void setTextField(CInterfaceGroup* scenarioWnd, const std::string &uiName viewText->setText(text); CGroupEditBox* editBox = dynamic_cast(result); if(editBox) - editBox->setInputString(text); + editBox->setInputStringAsUtf16(text); } } @@ -2824,7 +2824,7 @@ class CAHScenarioControl : public IActionHandler { CGroupEditBox* editBox = dynamic_cast(result); if(editBox) - editBox->setInputString(description); + editBox->setInputStringAsUtf16(description); } } } @@ -2975,7 +2975,7 @@ class CAHLoadScenario : public IActionHandler { CGroupEditBox* editBox = dynamic_cast(result); if(editBox) - description = editBox->getInputString().toString(); + description = editBox->getInputStringAsUtf8(); } // races diff --git a/ryzom/client/src/interface_v3/action_handler_edit.cpp b/ryzom/client/src/interface_v3/action_handler_edit.cpp index 00a07dd39..81837bf4a 100644 --- a/ryzom/client/src/interface_v3/action_handler_edit.cpp +++ b/ryzom/client/src/interface_v3/action_handler_edit.cpp @@ -27,6 +27,7 @@ using namespace NLMISC; #include "nel/gui/action_handler.h" #include "nel/gui/group_editbox.h" +#include "nel/misc/utf_string_view.h" #include "interface_manager.h" #include "../client_chat_manager.h" #include "people_interraction.h" @@ -56,7 +57,7 @@ extern CClientChatManager ChatMngr; // *************************************************************************** // used for character classifiction (when the user press Ctrl-arrow) -static inline uint getCharacterCategory(ucchar c) +static inline uint getCharacterCategory(u32char c) { if (c == ' ') return 0; if (c > 127 || isalpha((char) c)) return 1; // alpha & other characters @@ -69,7 +70,7 @@ static inline uint getCharacterCategory(ucchar c) /** skip a block of character in a string, (same behaviour than when Ctrl-arrow is pressed) * It returns the new index */ -static uint skipUCCharsRight(uint startPos, const ucstring &str) +static uint skipUCCharsRight(uint startPos, const u32string &str) { uint pos = startPos; uint endIndex = (uint)str.length(); @@ -86,7 +87,7 @@ static uint skipUCCharsRight(uint startPos, const ucstring &str) /** skip a block of character in a string, (same behaviour than when Ctrl-arrow is pressed) * It returns the new index */ -static uint skipUCCharsLeft(uint startPos, const ucstring &str) +static uint skipUCCharsLeft(uint startPos, const u32string &str) { uint pos = startPos; -- pos; @@ -362,7 +363,7 @@ class CAHEditPreviousLine : public CAHEdit if (_GroupEdit->getMaxHistoric() && (! _GroupEdit->getViewText()->getMultiLine())) { // Get the start of the string. - ucstring startStr= _GroupEdit->getInputStringRef().substr(0, _GroupEdit->getCursorPos()); + u32string startStr= _GroupEdit->getInputStringRef().substr(0, _GroupEdit->getCursorPos()); // Search all historic string that match startStr. for(sint i=_GroupEdit->getCurrentHistoricIndex()+1;i<(sint)_GroupEdit->getNumHistoric();i++) @@ -434,7 +435,7 @@ class CAHEditNextLine : public CAHEdit if( (! _GroupEdit->getViewText()->getMultiLine()) && _GroupEdit->getMaxHistoric() && _GroupEdit->getCurrentHistoricIndex()>0) { // Get the start of the string. - ucstring startStr= _GroupEdit->getInputStringRef().substr(0, _GroupEdit->getCursorPos()); + u32string startStr= _GroupEdit->getInputStringRef().substr(0, _GroupEdit->getCursorPos()); // Search all historic string that match startStr. for(sint i=_GroupEdit->getCurrentHistoricIndex()-1;i>=0;i--) @@ -520,8 +521,8 @@ protected: // else cut forwards else if(_GroupEdit->getCursorPos() < (sint32) _GroupEdit->getInputStringRef().length()) { - ucstring inputString = _GroupEdit->getInputStringRef(); - ucstring::iterator it = inputString.begin() + _GroupEdit->getCursorPos(); + u32string inputString = _GroupEdit->getInputStringRef(); + u32string::iterator it = inputString.begin() + _GroupEdit->getCursorPos(); inputString.erase(it); _GroupEdit->setInputStringRef (inputString); if (!_GroupEdit->getAHOnChange().empty()) @@ -638,7 +639,7 @@ class CAHEditExpandOrCycleTell : public CAHEdit void actionPart () { // If the line starts with '/tell ', do not try to expand - static const ucstring TELL_STR("/tell "); + static const u32string TELL_STR(CUtfStringView("/tell ").toUtf32()); if (_GroupEdit->getInputString().substr(0, TELL_STR.length()) != TELL_STR) { if (_GroupEdit->expand()) return; diff --git a/ryzom/client/src/interface_v3/action_handler_item.cpp b/ryzom/client/src/interface_v3/action_handler_item.cpp index af491257a..f984fe898 100644 --- a/ryzom/client/src/interface_v3/action_handler_item.cpp +++ b/ryzom/client/src/interface_v3/action_handler_item.cpp @@ -129,7 +129,7 @@ void CInterfaceItemEdition::CItemEditionWindow::infoReceived() { if ( pIS->Family == ITEMFAMILY::SCROLL) { - editBoxLarge->setInputString(itemInfo.CustomText); + editBoxLarge->setInputStringAsUtf16(itemInfo.CustomText); editLarge->setActive(true); editBoxLarge->setActive(true); @@ -147,7 +147,7 @@ void CInterfaceItemEdition::CItemEditionWindow::infoReceived() strFindReplace(customText, "%mfc", ucstring()); } - editBoxShort->setInputString(customText); + editBoxShort->setInputStringAsUtf16(customText); editShort->setActive(true); editBoxShort->setActive(true); @@ -231,8 +231,8 @@ void CInterfaceItemEdition::CItemEditionWindow::begin() closeButton->setActive(false); group->setActive(true); - editBoxShort->setInputString(ucstring()); - editBoxLarge->setInputString(ucstring()); + editBoxShort->setInputString(u32string()); + editBoxLarge->setInputString(u32string()); display->setTextFormatTaged(ucstring()); @@ -242,7 +242,7 @@ void CInterfaceItemEdition::CItemEditionWindow::begin() // If we already have item info if ( pIS->Family == ITEMFAMILY::SCROLL) { - editBoxLarge->setInputString(itemInfo.CustomText); + editBoxLarge->setInputStringAsUtf16(itemInfo.CustomText); editLarge->setActive(true); editBoxLarge->setActive(true); @@ -261,7 +261,7 @@ void CInterfaceItemEdition::CItemEditionWindow::begin() strFindReplace(customText, "%mfc", ucstring()); } - editBoxShort->setInputString(customText); + editBoxShort->setInputStringAsUtf16(customText); editShort->setActive(true); editBoxShort->setActive(true); @@ -289,8 +289,8 @@ void CInterfaceItemEdition::CItemEditionWindow::begin() closeButton->setActive(true); group->setActive(true); - editBoxShort->setInputString(ucstring()); - editBoxLarge->setInputString(ucstring()); + editBoxShort->setInputString(u32string()); + editBoxLarge->setInputString(u32string()); display->setTextFormatTaged(ucstring()); // Finish the display or add the waiter @@ -394,11 +394,11 @@ void CInterfaceItemEdition::CItemEditionWindow::validate() if (group && editShort && editBoxShort && editLarge && editBoxLarge && display && editButtons && closeButton && background) { bool textValid = editShort->getActive(); - ucstring text = editBoxShort->getInputString(); + ucstring text = editBoxShort->getInputStringAsUtf16(); if (!textValid) { textValid = editLarge->getActive(); - text = editBoxLarge->getInputString(); + text = editBoxLarge->getInputStringAsUtf16(); } if (textValid) diff --git a/ryzom/client/src/interface_v3/action_phrase_faber.cpp b/ryzom/client/src/interface_v3/action_phrase_faber.cpp index 40efedac0..d039444f9 100644 --- a/ryzom/client/src/interface_v3/action_phrase_faber.cpp +++ b/ryzom/client/src/interface_v3/action_phrase_faber.cpp @@ -718,7 +718,7 @@ void CActionPhraseFaber::startMpSelection(uint itemReqLine, uint mpSlot) if (eb) { CWidgetManager::getInstance()->setCaptureKeyboard(eb); - eb->setInputString(toString(maxQuantity)); + eb->setInputStringAsUtf8(toString(maxQuantity)); eb->setSelectionAll(); } } diff --git a/ryzom/client/src/interface_v3/bot_chat_page_create_guild.cpp b/ryzom/client/src/interface_v3/bot_chat_page_create_guild.cpp index b7ec631b9..105d4a180 100644 --- a/ryzom/client/src/interface_v3/bot_chat_page_create_guild.cpp +++ b/ryzom/client/src/interface_v3/bot_chat_page_create_guild.cpp @@ -70,10 +70,10 @@ class CHandlerGuildCreate : public IActionHandler CGroupEditBox *pDesc = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(guildDescWin)); - ucstring guildName = pGEB->getInputString(); + ucstring guildName = pGEB->getInputStringAsUtf16(); ucstring guildDesc; - if (pDesc != NULL) guildDesc = pDesc->getInputString(); + if (pDesc != NULL) guildDesc = pDesc->getInputStringAsUtf16(); uint64 icon = CGuildManager::iconMake((uint8)pCS->getGuildBack(), (uint8)pCS->getGuildSymbol(), pCS->getInvertGuildSymbol(), pCS->getGuildColor1(), pCS->getGuildColor2()); diff --git a/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp b/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp index 4a59163b3..64f19214f 100644 --- a/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp +++ b/ryzom/client/src/interface_v3/bot_chat_page_trade.cpp @@ -333,7 +333,7 @@ uint32 CBotChatPageTrade::getCurrItemQuantity() const CGroupEditBox *ed = dynamic_cast(ig->getGroup("header_opened:standard_price:quantity:edit:eb")); if (!ed) return std::numeric_limits::max(); uint32 intQuantity; - if (fromString(ed->getInputString().toString(), intQuantity)) + if (fromString(ed->getInputStringAsUtf8(), intQuantity)) { return intQuantity; } @@ -1465,7 +1465,7 @@ void CBotChatPageTrade::setupPriceGroupQuantity(CInterfaceGroup *priceGroup, sin CGroupEditBox *eb = dynamic_cast(quantityGroup->getGroup("edit:eb")); if (eb) { - eb->setInputString(toString(defaultQuantity)); + eb->setInputStringAsUtf8(toString(defaultQuantity)); } } } @@ -1569,7 +1569,7 @@ void CBotChatPageTrade::setupResellGroup(bool sellMode, uint defaultQuantity, CI { sint32 resaleMargin= NLGUI::CDBManager::getInstance()->getDbProp( "UI:SAVE:TRADE_ITEM:RESALE_MARGIN" )->getValue32(); clamp(resaleMargin, 0, (sint32)MaxResaleMargin); - eb->setInputString( toString( resaleMargin ) ); + eb->setInputStringAsUtf8( toString( resaleMargin ) ); eb->setPositiveIntegerMaxValue(MaxResaleMargin); } } @@ -1725,8 +1725,8 @@ void CBotChatPageTrade::startChangeBuyFilterDialog(const std::string &dbext, con sint rangeMax= 0; if(dbRangeMin) rangeMin= dbRangeMin->getValue32(); if(dbRangeMax) rangeMax= dbRangeMax->getValue32(); - if(edMin) edMin->setInputString(toString(rangeMin)); - if(edMax) edMax->setInputString(toString(rangeMax)); + if(edMin) edMin->setInputStringAsUtf8(toString(rangeMin)); + if(edMax) edMax->setInputStringAsUtf8(toString(rangeMax)); if(edMin) edMin->setPositiveIntegerMaxValue(maxValue); if(edMax) edMax->setPositiveIntegerMaxValue(maxValue); @@ -1754,8 +1754,8 @@ void CBotChatPageTrade::resetBuyFilterDialog() sint rangeMin= 0; sint rangeMax= _FilterBuyDlgMaxValue; // write result in EditBox, and in db - if(edMin) edMin->setInputString(toString(rangeMin)); - if(edMax) edMax->setInputString(toString(rangeMax)); + if(edMin) edMin->setInputStringAsUtf8(toString(rangeMin)); + if(edMax) edMax->setInputStringAsUtf8(toString(rangeMax)); if(dbRangeMin) dbRangeMin->setValue32(rangeMin); if(dbRangeMax) dbRangeMax->setValue32(rangeMax); diff --git a/ryzom/client/src/interface_v3/chat_window.cpp b/ryzom/client/src/interface_v3/chat_window.cpp index 1537e7b8b..bfac81212 100644 --- a/ryzom/client/src/interface_v3/chat_window.cpp +++ b/ryzom/client/src/interface_v3/chat_window.cpp @@ -363,7 +363,7 @@ void CChatWindow::setCommand(const ucstring &command,bool execute) void CChatWindow::setEntry(const ucstring &entry) { if (!_EB) return; - _EB->setInputString(entry); + _EB->setInputStringAsUtf16(entry); } //================================================================================= @@ -1273,7 +1273,7 @@ public: { CGroupEditBox *pEB = dynamic_cast(pCaller); if (pEB == NULL) return; - ucstring text = pEB->getInputString(); + ucstring text = pEB->getInputStringAsUtf16(); // If the line is empty, do nothing if(text.empty()) return; @@ -1289,7 +1289,7 @@ public: // Parse any tokens in the text if ( ! CInterfaceManager::parseTokens(text)) { - pEB->setInputString (string("")); + pEB->setInputString (u32string()); return; } @@ -1329,7 +1329,7 @@ public: } } // Clear input string - pEB->setInputString (ucstring("")); + pEB->setInputString (u32string()); CGroupContainer *gc = static_cast< CGroupContainer* >( pEB->getEnclosingContainer() ); if (gc) diff --git a/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp b/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp index 3cd8e759c..8ffa62530 100644 --- a/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp +++ b/ryzom/client/src/interface_v3/dbgroup_build_phrase.cpp @@ -279,7 +279,7 @@ void CDBGroupBuildPhrase::clearBuildingPhrase() // Empty the name if(_UserSentenceName) { - _UserSentenceName->setInputString(ucstring()); + _UserSentenceName->setInputString(u32string()); } // update Display @@ -373,7 +373,7 @@ void CDBGroupBuildPhrase::startComposition(const CSPhraseCom &phrase) // set the editable name. if(_UserSentenceName) - _UserSentenceName->setInputString(name); + _UserSentenceName->setInputStringAsUtf16(name); } @@ -1790,7 +1790,7 @@ void CDBGroupBuildPhrase::buildCurrentPhrase(CSPhraseCom &newPhrase) // Set the Name if(_UserSentenceName) { - newPhrase.Name= _UserSentenceName->getInputString(); + newPhrase.Name= _UserSentenceName->getInputStringAsUtf16(); } } diff --git a/ryzom/client/src/interface_v3/group_map.cpp b/ryzom/client/src/interface_v3/group_map.cpp index 4b08b6e4b..097d2d80c 100644 --- a/ryzom/client/src/interface_v3/group_map.cpp +++ b/ryzom/client/src/interface_v3/group_map.cpp @@ -141,12 +141,12 @@ static void popupLandMarkNameDialog() const CUserLandMark userLM = map->getUserLandMark(LastSelectedLandMark); NLGUI::CDBManager::getInstance()->getDbProp( "UI:TEMP:LANDMARKTYPE" )->setValue8(cb->getTextPos(userLM.Type)); - eb->setInputString(userLM.Title); + eb->setInputStringAsUtf16(userLM.Title); } else { NLGUI::CDBManager::getInstance()->getDbProp( "UI:TEMP:LANDMARKTYPE" )->setValue8(cb->getTextPos(CUserLandMark::Misc)); - eb->setInputString(ucstring()); + eb->setInputStringAsUtf16(ucstring()); } CWidgetManager::getInstance()->setCaptureKeyboard(eb); @@ -3718,7 +3718,7 @@ class CAHLandMarkFilter : public IActionHandler CGroupEditBox* eb = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(group)); if (!eb) return; - text = eb->getInputString().toUtf8(); + text = eb->getInputStringAsUtf8(); } map->setLandmarkFilter(text); @@ -3824,7 +3824,7 @@ class CAHValidateUserLandMarkName : public IActionHandler CGroupMap *map = dynamic_cast(LastSelectedLandMark->getParent()); if (!map) return; // update existing landmark - map->updateUserLandMark(LastSelectedLandMark, eb->getInputString(), landMarkType); + map->updateUserLandMark(LastSelectedLandMark, eb->getInputStringAsUtf16(), landMarkType); } else { @@ -3832,11 +3832,11 @@ class CAHValidateUserLandMarkName : public IActionHandler if (!LastClickedMap) return; if( UseUserPositionForLandMark ) { - LastClickedMap->addUserLandMark(LastClickedMap->getPlayerPos(), eb->getInputString(), landMarkType); + LastClickedMap->addUserLandMark(LastClickedMap->getPlayerPos(), eb->getInputStringAsUtf16(), landMarkType); } else { - LastClickedMap->addUserLandMark(LastClickedMap->getRightClickLastPos(), eb->getInputString(), landMarkType); + LastClickedMap->addUserLandMark(LastClickedMap->getRightClickLastPos(), eb->getInputStringAsUtf16(), landMarkType); } LastClickedMap->invalidateCoords(); } diff --git a/ryzom/client/src/interface_v3/inventory_manager.cpp b/ryzom/client/src/interface_v3/inventory_manager.cpp index 71e486560..a3ac69709 100644 --- a/ryzom/client/src/interface_v3/inventory_manager.cpp +++ b/ryzom/client/src/interface_v3/inventory_manager.cpp @@ -2726,7 +2726,7 @@ class CHandlerInvSearchButton : public IActionHandler { CWidgetManager::getInstance()->setCaptureKeyboard(eb); eb->setSelectionAll(); - filter = eb->getInputString(); + filter = eb->getInputStringAsUtf16(); } CDBGroupListSheetBag *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(btn->getParent()->getId() + ":bag_list")); @@ -2776,10 +2776,10 @@ class CHandlerInvSetSearch : public IActionHandler std::string id = pCaller->getParent()->getParent()->getId(); CDBGroupListSheetBag *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id + ":bag_list")); - if (pList != NULL) pList->setSearchFilter(eb->getInputString()); + if (pList != NULL) pList->setSearchFilter(eb->getInputStringAsUtf16()); CDBGroupIconListBag *pIcons = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(id + ":bag_icons")); - if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputString()); + if (pIcons != NULL) pIcons->setSearchFilter(eb->getInputStringAsUtf16()); } }; REGISTER_ACTION_HANDLER( CHandlerInvSetSearch, "inv_set_search" ); diff --git a/ryzom/client/src/interface_v3/macrocmd_key.cpp b/ryzom/client/src/interface_v3/macrocmd_key.cpp index 7f4c26c08..241862ff1 100644 --- a/ryzom/client/src/interface_v3/macrocmd_key.cpp +++ b/ryzom/client/src/interface_v3/macrocmd_key.cpp @@ -1148,7 +1148,7 @@ void CModalContainerEditCmd::onChangeAction() CGroupEditBox *pEB= dynamic_cast(CWidgetManager::getInstance()->getElementFromId( sWin )); if( pEB ) { - pEB->setInputString(ucstring("")); + pEB->setInputString(u32string()); } NLGUI::CDBManager::getInstance()->getDbProp( sDB )->setValue32(1); } diff --git a/ryzom/client/src/interface_v3/macrocmd_manager.cpp b/ryzom/client/src/interface_v3/macrocmd_manager.cpp index 6aa831eac..39b2aedde 100644 --- a/ryzom/client/src/interface_v3/macrocmd_manager.cpp +++ b/ryzom/client/src/interface_v3/macrocmd_manager.cpp @@ -886,7 +886,7 @@ public: if (pCS != NULL) pCS->readFromMacro(pMCM->CurrentEditMacro); // Name CGroupEditBox *pEB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_NEWMACRO_EDIT_NAME)); - if (pEB != NULL) pEB->setInputString(pMCM->CurrentEditMacro.Name); + if (pEB != NULL) pEB->setInputStringAsUtf8(pMCM->CurrentEditMacro.Name); // Commands CGroupList *pList = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(GROUP_NEWMACRO_COMMANDS)); if (pList == NULL) return; diff --git a/ryzom/client/src/interface_v3/people_interraction.cpp b/ryzom/client/src/interface_v3/people_interraction.cpp index 96f27bb6c..21cfb63cf 100644 --- a/ryzom/client/src/interface_v3/people_interraction.cpp +++ b/ryzom/client/src/interface_v3/people_interraction.cpp @@ -2199,7 +2199,7 @@ public: if (gc) { CGroupEditBox *geb = dynamic_cast(gc->getGroup("add_contact_eb:eb")); - geb->setInputString(ucstring("")); + geb->setInputString(u32string()); } CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, sParams); } @@ -2250,18 +2250,18 @@ public: if (peopleList) { // don't add if it is the player name - if (!ClientCfg.Local && (UserEntity->getEntityName() == geb->getInputString())) + if (!ClientCfg.Local && (UserEntity->getEntityName() == geb->getInputStringAsUtf16())) { displayVisibleSystemMsg(CI18N::get("uiCantAddYourSelfInContactList")); } else { - PeopleInterraction.askAddContact(geb->getInputString(), peopleList); - geb->setInputString(ucstring("")); + PeopleInterraction.askAddContact(geb->getInputStringAsUtf16(), peopleList); + geb->setInputString(u32string()); } } } - geb->setInputString(ucstring("")); + geb->setInputString(u32string()); } } } @@ -2389,7 +2389,7 @@ public: if (eb) { CWidgetManager::getInstance()->setCaptureKeyboard(eb); - eb->setInputString(ucstring("")); + eb->setInputString(u32string()); } // if (gc->getActive()) @@ -2416,7 +2416,7 @@ class CHandlerValidatePartyChatName : public IActionHandler if (!gc) return; CGroupEditBox *eb = dynamic_cast(gc->getGroup("eb")); if (!eb) return; - ucstring title = eb->getInputString(); + ucstring title = eb->getInputStringAsUtf16(); // TODO GAMEDEV : create (or join ?) a new channel. Each channel (party chat) should have a unique name in the game // moreover, it should not have the name of another available chat window (for example, it shouldn't be named 'Around Me') diff --git a/ryzom/client/src/interface_v3/people_list.cpp b/ryzom/client/src/interface_v3/people_list.cpp index 6be310d94..43ee1543c 100644 --- a/ryzom/client/src/interface_v3/people_list.cpp +++ b/ryzom/client/src/interface_v3/people_list.cpp @@ -876,7 +876,7 @@ class CHandlerContactEntry : public IActionHandler { CGroupEditBox *pEB = dynamic_cast(pCaller); if (pEB == NULL) return; - ucstring text = pEB->getInputString(); + ucstring text = pEB->getInputStringAsUtf16(); // If the line is empty, do nothing if(text.empty()) return; @@ -884,7 +884,7 @@ class CHandlerContactEntry : public IActionHandler // Parse any tokens in the text if ( ! CInterfaceManager::parseTokens(text)) { - pEB->setInputString (string("")); + pEB->setInputString (u32string()); return; } @@ -895,7 +895,7 @@ class CHandlerContactEntry : public IActionHandler // TODO : have NLMISC::ICommand accept unicode strings std::string str = text.toUtf8().substr(1); NLMISC::ICommand::execute( str, g_log ); - pEB->setInputString (string("")); + pEB->setInputString (u32string()); return; } // Well, we could have used CChatWindow class to handle this, but CPeopleList was written earlier, so for now @@ -908,7 +908,7 @@ class CHandlerContactEntry : public IActionHandler // Simply do a tell on the player ChatMngr.tell(playerName.toString(), text); - pEB->setInputString (string("")); + pEB->setInputString (u32string()); if (gc) { // Restore position of enclosing container if it hasn't been moved/scaled/poped by the user diff --git a/ryzom/client/src/login.cpp b/ryzom/client/src/login.cpp index 96922d399..6f3617286 100644 --- a/ryzom/client/src/login.cpp +++ b/ryzom/client/src/login.cpp @@ -808,7 +808,7 @@ void initLoginScreen() CGroupEditBox *pGEB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN)); if (pGEB != NULL && (pGEB->getInputString().empty())) { - pGEB->setInputString(l); + pGEB->setInputStringAsUtf8(l); } CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_PASSWORD "|select_all=false"); } @@ -830,8 +830,8 @@ void initAutoLogin() CInterfaceManager *pIM = CInterfaceManager::getInstance(); CGroupEditBox *pGEBLog = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_LOGIN)); CGroupEditBox *pGEBPwd = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(CTRL_EDITBOX_PASSWORD)); - pGEBLog->setInputString(LoginLogin); - pGEBPwd->setInputString(LoginPassword); + pGEBLog->setInputStringAsUtf8(LoginLogin); + pGEBPwd->setInputStringAsUtf8(LoginPassword); CAHManager::getInstance()->runActionHandler("on_login", NULL, ""); if (ClientCfg.R2Mode) @@ -1379,8 +1379,8 @@ class CAHOnLogin : public IActionHandler return; } - LoginLogin = pGEBLog->getInputString().toString(); // FIXME: Unicode login - LoginPassword = pGEBPwd->getInputString().toString(); + LoginLogin = pGEBLog->getInputStringAsUtf8(); + LoginPassword = pGEBPwd->getInputStringAsUtf8(); onlogin(); } @@ -2394,7 +2394,7 @@ bool initCreateAccount() { CGroupEditBox * eb = dynamic_cast(createAccountUI->findFromShortId(editBoxes[i] + ":eb")); if(eb) - eb->setInputString(ucstring("")); + eb->setInputString(u32string()); } // conditions button @@ -2581,7 +2581,7 @@ class CAHOnCreateAccountSubmit : public IActionHandler { CGroupEditBox * eb = dynamic_cast(createAccountUI->findFromShortId(editBoxes[i] + ":eb")); if(eb) - results[i] = eb->getInputString().toUtf8(); + results[i] = eb->getInputStringAsUtf8(); } // text @@ -2735,11 +2735,11 @@ class CAHCreateAccountLogin : public IActionHandler { CGroupEditBox * eb = dynamic_cast(createAccountUI->findFromShortId("eb_login:eb")); if(eb) - LoginLogin = eb->getInputString().toUtf8(); + LoginLogin = eb->getInputStringAsUtf8(); eb = dynamic_cast(createAccountUI->findFromShortId("eb_password:eb")); if(eb) - LoginPassword = eb->getInputString().toUtf8(); + LoginPassword = eb->getInputStringAsUtf8(); onlogin(false); } diff --git a/ryzom/client/src/r2/editor.cpp b/ryzom/client/src/r2/editor.cpp index 36801ad9f..e903785e7 100644 --- a/ryzom/client/src/r2/editor.cpp +++ b/ryzom/client/src/r2/editor.cpp @@ -7484,7 +7484,7 @@ class CAHInviteCharacter : public IActionHandler CGroupEditBox *geb = dynamic_cast(fatherGC->getGroup("add_contact_eb:eb")); if (geb && !geb->getInputString().empty()) { - string charName = geb->getInputString().toString(); + string charName = geb->getInputStringAsUtf8(); CSessionBrowserImpl & sessionBrowser = CSessionBrowserImpl::getInstance(); sessionBrowser.inviteCharacterByName(sessionBrowser.getCharId(), charName); @@ -7506,7 +7506,7 @@ class CAHInviteCharacter : public IActionHandler CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:warning_newcomer"); } - geb->setInputString(ucstring("")); + geb->setInputString(u32string()); } } }