diff options
Diffstat (limited to '')
-rw-r--r-- | src/irrlicht_changes/static_text.cpp (renamed from src/util/statictext.cpp) | 139 | ||||
-rw-r--r-- | src/irrlicht_changes/static_text.h (renamed from src/util/statictext.h) | 122 | ||||
-rw-r--r-- | src/util/CMakeLists.txt | 11 | ||||
-rw-r--r-- | src/util/coloredstring.cpp | 68 | ||||
-rw-r--r-- | src/util/coloredstring.h | 44 | ||||
-rw-r--r-- | src/util/enriched_string.cpp | 166 | ||||
-rw-r--r-- | src/util/enriched_string.h | 91 | ||||
-rw-r--r-- | src/util/string.h | 32 |
8 files changed, 492 insertions, 181 deletions
diff --git a/src/util/statictext.cpp b/src/irrlicht_changes/static_text.cpp index b534b560e..703287eb3 100644 --- a/src/util/statictext.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -1,12 +1,12 @@ // Copyright (C) 2002-2012 Nikolaus Gebhardt +// Copyright (C) 2016 Nathanaël Courant: +// Modified the functions to use EnrichedText instead of string. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "statictext.h" +#include "static_text.h" #ifdef _IRR_COMPILE_WITH_GUI_ -//Only compile this if freetype is enabled. - #include <vector> #include <string> #include <iostream> @@ -17,15 +17,21 @@ #include <rect.h> #include <SColor.h> -#include "cguittfont/xCGUITTFont.h" +#if USE_FREETYPE + #include "cguittfont/xCGUITTFont.h" +#endif + #include "util/string.h" namespace irr { + +#if USE_FREETYPE + namespace gui { //! constructor -StaticText::StaticText(const wchar_t* text, bool border, +StaticText::StaticText(const EnrichedString &text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect<s32>& rectangle, bool background) @@ -40,7 +46,8 @@ StaticText::StaticText(const wchar_t* text, bool border, setDebugName("StaticText"); #endif - Text = text; + Text = text.c_str(); + cText = text; if (environment && environment->getSkin()) { BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE); @@ -55,7 +62,6 @@ StaticText::~StaticText() OverrideFont->drop(); } - //! draws the element and its children void StaticText::draw() { @@ -88,7 +94,7 @@ void StaticText::draw() } // draw the text - if (Text.size()) + if (cText.size()) { IGUIFont* font = getActiveFont(); @@ -105,10 +111,11 @@ void StaticText::draw() if (HAlign == EGUIA_LOWERRIGHT) { frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - - font->getDimension(Text.c_str()).Width; + font->getDimension(cText.c_str()).Width; } - font->draw(Text.c_str(), frameRect, + irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font); + tmp->draw(cText, frameRect, OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } @@ -138,16 +145,17 @@ void StaticText::draw() font->getDimension(BrokenText[i].c_str()).Width; } - std::vector<irr::video::SColor> colors; - std::wstring str; + //std::vector<irr::video::SColor> colors; + //std::wstring str; + EnrichedString str = BrokenText[i]; - str = colorizeText(BrokenText[i].c_str(), colors, previous_color); - if (!colors.empty()) - previous_color = colors[colors.size() - 1]; + //str = colorizeText(BrokenText[i].c_str(), colors, previous_color); + //if (!colors.empty()) + // previous_color = colors[colors.size() - 1]; irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font); - tmp->draw(str.c_str(), r, - colors, + tmp->draw(str, r, + previous_color, // FIXME HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); r.LowerRightCorner.Y += height; @@ -340,17 +348,17 @@ void StaticText::breakText() LastBreakFont = font; - core::stringw line; - core::stringw word; - core::stringw whitespace; - s32 size = Text.size(); + EnrichedString line; + EnrichedString word; + EnrichedString whitespace; + s32 size = cText.size(); s32 length = 0; s32 elWidth = RelativeRect.getWidth(); if (Border) elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X); wchar_t c; - std::vector<irr::video::SColor> colors; + //std::vector<irr::video::SColor> colors; // We have to deal with right-to-left and left-to-right differently // However, most parts of the following code is the same, it's just @@ -360,17 +368,17 @@ void StaticText::breakText() // regular (left-to-right) for (s32 i=0; i<size; ++i) { - c = Text[i]; + c = cText.getString()[i]; bool lineBreak = false; if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - if (Text[i+1] == L'\n') // Windows breaks - { - Text.erase(i+1); - --size; - } + //if (Text[i+1] == L'\n') // Windows breaks + //{ + // Text.erase(i+1); + // --size; + //} c = '\0'; } else if (c == L'\n') // Unix breaks @@ -383,7 +391,8 @@ void StaticText::breakText() if ( !isWhitespace ) { // part of a word - word += c; + //word += c; + word.addChar(cText, i); } if ( isWhitespace || i == (size-1)) @@ -393,20 +402,21 @@ void StaticText::breakText() // here comes the next whitespace, look if // we must break the last word to the next line. const s32 whitelgth = font->getDimension(whitespace.c_str()).Width; - const std::wstring sanitized = removeEscapes(word.c_str()); - const s32 wordlgth = font->getDimension(sanitized.c_str()).Width; + //const std::wstring sanitized = removeEscapes(word.c_str()); + const s32 wordlgth = font->getDimension(word.c_str()).Width; if (wordlgth > elWidth) { // This word is too long to fit in the available space, look for // the Unicode Soft HYphen (SHY / 00AD) character for a place to // break the word at - int where = word.findFirst( wchar_t(0x00AD) ); + int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) ); if (where != -1) { - core::stringw first = word.subString(0, where); - core::stringw second = word.subString(where, word.size() - where); - BrokenText.push_back(line + first + L"-"); + EnrichedString first = word.substr(0, where); + EnrichedString second = word.substr(where, word.size() - where); + first.addCharNoColor(L'-'); + BrokenText.push_back(line + first); const s32 secondLength = font->getDimension(second.c_str()).Width; length = secondLength; @@ -437,13 +447,13 @@ void StaticText::breakText() length += whitelgth + wordlgth; } - word = L""; - whitespace = L""; + word.clear(); + whitespace.clear(); } - if ( isWhitespace ) + if ( isWhitespace && c != 0) { - whitespace += c; + whitespace.addChar(cText, i); } // compute line break @@ -452,9 +462,9 @@ void StaticText::breakText() line += whitespace; line += word; BrokenText.push_back(line); - line = L""; - word = L""; - whitespace = L""; + line.clear(); + word.clear(); + whitespace.clear(); length = 0; } } @@ -469,17 +479,17 @@ void StaticText::breakText() // right-to-left for (s32 i=size; i>=0; --i) { - c = Text[i]; + c = cText.getString()[i]; bool lineBreak = false; if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - if ((i>0) && Text[i-1] == L'\n') // Windows breaks - { - Text.erase(i-1); - --size; - } + //if ((i>0) && Text[i-1] == L'\n') // Windows breaks + //{ + // Text.erase(i-1); + // --size; + //} c = '\0'; } else if (c == L'\n') // Unix breaks @@ -512,12 +522,13 @@ void StaticText::breakText() length += whitelgth + wordlgth; } - word = L""; - whitespace = L""; + word.clear(); + whitespace.clear(); } if (c != 0) - whitespace = core::stringw(&c, 1) + whitespace; + // whitespace = core::stringw(&c, 1) + whitespace; + whitespace = cText.substr(i, 1) + whitespace; // compute line break if (lineBreak) @@ -525,16 +536,17 @@ void StaticText::breakText() line = whitespace + line; line = word + line; BrokenText.push_back(line); - line = L""; - word = L""; - whitespace = L""; + line.clear(); + word.clear(); + whitespace.clear(); length = 0; } } else { // yippee this is a word.. - word = core::stringw(&c, 1) + word; + //word = core::stringw(&c, 1) + word; + word = cText.substr(i, 1) + word; } } @@ -548,7 +560,17 @@ void StaticText::breakText() //! Sets the new caption of this element. void StaticText::setText(const wchar_t* text) { - IGUIElement::setText(text); + setText(EnrichedString(text)); +} + +//! Sets the new caption of this element. +void StaticText::setText(const EnrichedString &text) +{ + IGUIElement::setText(text.c_str()); + cText = text; + if (text.hasBackground()) { + setBackgroundColor(text.getBackground()); + } breakText(); } @@ -598,7 +620,7 @@ s32 StaticText::getTextWidth() const } else { - return font->getDimension(Text.c_str()).Width; + return font->getDimension(cText.c_str()).Width; } } @@ -648,6 +670,9 @@ void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWr } } // end namespace gui + +#endif // USE_FREETYPE + } // end namespace irr diff --git a/src/util/statictext.h b/src/irrlicht_changes/static_text.h index 8d2f879e7..408a12784 100644 --- a/src/util/statictext.h +++ b/src/irrlicht_changes/static_text.h @@ -1,4 +1,6 @@ // Copyright (C) 2002-2012 Nikolaus Gebhardt +// Copyright (C) 2016 Nathanaël Courant +// Modified this class to work with EnrichedStrings too // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -11,18 +13,30 @@ #include "IGUIStaticText.h" #include "irrArray.h" +#include "log.h" + #include <vector> +#include "util/enriched_string.h" +#include "config.h" +#include <IGUIEnvironment.h> + +#if USE_FREETYPE + namespace irr { + namespace gui { + + const EGUI_ELEMENT_TYPE EGUIET_ENRICHED_STATIC_TEXT = (EGUI_ELEMENT_TYPE)(0x1000); + class StaticText : public IGUIStaticText { public: //! constructor - StaticText(const wchar_t* text, bool border, IGUIEnvironment* environment, + StaticText(const EnrichedString &text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect<s32>& rectangle, bool background = false); @@ -121,6 +135,16 @@ namespace gui //! Reads attributes of the element virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual bool hasType(EGUI_ELEMENT_TYPE t) const { + return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); + }; + + virtual bool hasType(EGUI_ELEMENT_TYPE t) { + return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); + }; + + void setText(const EnrichedString &text); + private: //! Breaks the single text line. @@ -139,12 +163,106 @@ namespace gui gui::IGUIFont* OverrideFont; gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated. - core::array< core::stringw > BrokenText; + EnrichedString cText; + core::array< EnrichedString > BrokenText; }; + } // end namespace gui + } // end namespace irr +inline irr::gui::IGUIStaticText *addStaticText( + irr::gui::IGUIEnvironment *guienv, + const EnrichedString &text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, + bool fillBackground = false) +{ + if (parent == NULL) { + // parent is NULL, so we must find one, or we need not to drop + // result, but then there will be a memory leak. + // + // What Irrlicht does is to use guienv as a parent, but the problem + // is that guienv is here only an IGUIEnvironment, while it is a + // CGUIEnvironment in Irrlicht, which inherits from both IGUIElement + // and IGUIEnvironment. + // + // A solution would be to dynamic_cast guienv to a + // IGUIElement*, but Irrlicht is shipped without rtti support + // in some distributions, causing the dymanic_cast to segfault. + // + // Thus, to find the parent, we create a dummy StaticText and ask + // for its parent, and then remove it. + irr::gui::IGUIStaticText *dummy_text = + guienv->addStaticText(L"", rectangle, border, wordWrap, + parent, id, fillBackground); + parent = dummy_text->getParent(); + dummy_text->remove(); + } + irr::gui::IGUIStaticText *result = new irr::gui::StaticText( + text, border, guienv, parent, + id, rectangle, fillBackground); + + result->setWordWrap(wordWrap); + result->drop(); + return result; +} + +inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text) +{ + // dynamic_cast not possible due to some distributions shipped + // without rtti support in irrlicht + if (static_text->hasType(irr::gui::EGUIET_ENRICHED_STATIC_TEXT)) { + irr::gui::StaticText* stext = static_cast<irr::gui::StaticText*>(static_text); + stext->setText(text); + } else { + static_text->setText(text.c_str()); + } +} + +#else // USE_FREETYPE + +inline irr::gui::IGUIStaticText *addStaticText( + irr::gui::IGUIEnvironment *guienv, + const EnrichedString &text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, + bool fillBackground = false) +{ + return guienv->addStaticText(text.c_str(), rectangle, border, wordWrap, parent, id, fillBackground); +} + +inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text) +{ + static_text->setText(text.c_str()); +} + +#endif + +inline irr::gui::IGUIStaticText *addStaticText( + irr::gui::IGUIEnvironment *guienv, + const wchar_t *text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, + bool fillBackground = false) { + return addStaticText(guienv, EnrichedString(text), rectangle, border, wordWrap, parent, id, fillBackground); +} + +inline void setStaticText(irr::gui::IGUIStaticText *static_text, const wchar_t *text) +{ + setStaticText(static_text, EnrichedString(text)); +} + #endif // _IRR_COMPILE_WITH_GUI_ #endif // C_GUI_STATIC_TEXT_H_INCLUDED diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index e028a0435..f571ab22c 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,17 +1,9 @@ -if(USE_FREETYPE) - set(UTIL_FREETYPEDEP_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/statictext.cpp - ) -else() - set(UTIL_FREETYPEDEP_SRCS ) -endif(USE_FREETYPE) - set(UTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/areastore.cpp ${CMAKE_CURRENT_SOURCE_DIR}/auth.cpp ${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/coloredstring.cpp ${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp ${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp @@ -20,6 +12,5 @@ set(UTIL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/srp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timetaker.cpp - ${UTIL_FREETYPEDEP_SRCS} PARENT_SCOPE) diff --git a/src/util/coloredstring.cpp b/src/util/coloredstring.cpp deleted file mode 100644 index 7db586550..000000000 --- a/src/util/coloredstring.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "coloredstring.h" -#include "util/string.h" - -ColoredString::ColoredString() -{} - -ColoredString::ColoredString(const std::wstring &string, const std::vector<SColor> &colors): - m_string(string), - m_colors(colors) -{} - -ColoredString::ColoredString(const std::wstring &s) { - m_string = colorizeText(s, m_colors, SColor(255, 255, 255, 255)); -} - -void ColoredString::operator=(const wchar_t *str) { - m_string = colorizeText(str, m_colors, SColor(255, 255, 255, 255)); -} - -size_t ColoredString::size() const { - return m_string.size(); -} - -ColoredString ColoredString::substr(size_t pos, size_t len) const { - if (pos == m_string.length()) - return ColoredString(); - if (len == std::string::npos || pos + len > m_string.length()) { - return ColoredString( - m_string.substr(pos, std::string::npos), - std::vector<SColor>(m_colors.begin() + pos, m_colors.end()) - ); - } else { - return ColoredString( - m_string.substr(pos, len), - std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len) - ); - } -} - -const wchar_t *ColoredString::c_str() const { - return m_string.c_str(); -} - -const std::vector<SColor> &ColoredString::getColors() const { - return m_colors; -} - -const std::wstring &ColoredString::getString() const { - return m_string; -} diff --git a/src/util/coloredstring.h b/src/util/coloredstring.h deleted file mode 100644 index a6d98db30..000000000 --- a/src/util/coloredstring.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef COLOREDSTRING_HEADER -#define COLOREDSTRING_HEADER - -#include <string> -#include <vector> -#include <SColor.h> - -using namespace irr::video; - -class ColoredString { -public: - ColoredString(); - ColoredString(const std::wstring &s); - ColoredString(const std::wstring &string, const std::vector<SColor> &colors); - void operator=(const wchar_t *str); - size_t size() const; - ColoredString substr(size_t pos = 0, size_t len = std::string::npos) const; - const wchar_t *c_str() const; - const std::vector<SColor> &getColors() const; - const std::wstring &getString() const; -private: - std::wstring m_string; - std::vector<SColor> m_colors; -}; - -#endif diff --git a/src/util/enriched_string.cpp b/src/util/enriched_string.cpp new file mode 100644 index 000000000..a7fc3a828 --- /dev/null +++ b/src/util/enriched_string.cpp @@ -0,0 +1,166 @@ +/* +Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is> +Copyright (C) 2016 Nore, Nathanaël Courant <nore@mesecons.net> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "enriched_string.h" +#include "util/string.h" +#include "log.h" +using namespace irr::video; + +EnrichedString::EnrichedString() +{ + clear(); +} + +EnrichedString::EnrichedString(const std::wstring &string, + const std::vector<SColor> &colors): + m_string(string), + m_colors(colors), + m_has_background(false) +{} + +EnrichedString::EnrichedString(const std::wstring &s, const SColor &color) +{ + clear(); + addAtEnd(s, color); +} + +EnrichedString::EnrichedString(const wchar_t *str, const SColor &color) +{ + clear(); + addAtEnd(std::wstring(str), color); +} + +void EnrichedString::operator=(const wchar_t *str) +{ + clear(); + addAtEnd(std::wstring(str), SColor(255, 255, 255, 255)); +} + +void EnrichedString::addAtEnd(const std::wstring &s, const SColor &initial_color) +{ + SColor color(initial_color); + size_t i = 0; + while (i < s.length()) { + if (s[i] != L'\x1b') { + m_string += s[i]; + m_colors.push_back(color); + ++i; + continue; + } + ++i; + size_t start_index = i; + size_t length; + if (i == s.length()) { + break; + } + if (s[i] == L'(') { + ++i; + ++start_index; + while (i < s.length() && s[i] != L')') { + if (s[i] == L'\\') { + ++i; + } + ++i; + } + length = i - start_index; + ++i; + } else { + ++i; + length = 1; + } + std::wstring escape_sequence(s, start_index, length); + std::vector<std::wstring> parts = split(escape_sequence, L'@'); + if (parts[0] == L"c") { + if (parts.size() < 2) { + continue; + } + parseColorString(wide_to_utf8(parts[1]), color, true); + } else if (parts[0] == L"b") { + if (parts.size() < 2) { + continue; + } + parseColorString(wide_to_utf8(parts[1]), m_background, true); + m_has_background = true; + } + continue; + } +} + +void EnrichedString::addChar(const EnrichedString &source, size_t i) +{ + m_string += source.m_string[i]; + m_colors.push_back(source.m_colors[i]); +} + +void EnrichedString::addCharNoColor(wchar_t c) +{ + m_string += c; + if (m_colors.empty()) { + m_colors.push_back(SColor(255, 255, 255, 255)); + } else { + m_colors.push_back(m_colors[m_colors.size() - 1]); + } +} + +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); +} + +void EnrichedString::operator+=(const EnrichedString &other) +{ + m_string += other.m_string; + m_colors.insert(m_colors.end(), other.m_colors.begin(), other.m_colors.end()); +} + +EnrichedString EnrichedString::substr(size_t pos, size_t len) const +{ + 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()) + ); + } else { + return EnrichedString( + m_string.substr(pos, len), + std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len) + ); + } +} + +const wchar_t *EnrichedString::c_str() const +{ + return m_string.c_str(); +} + +const std::vector<SColor> &EnrichedString::getColors() const +{ + return m_colors; +} + +const std::wstring &EnrichedString::getString() const +{ + return m_string; +} diff --git a/src/util/enriched_string.h b/src/util/enriched_string.h new file mode 100644 index 000000000..1aca8948a --- /dev/null +++ b/src/util/enriched_string.h @@ -0,0 +1,91 @@ +/* +Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is> +Copyright (C) 2016 Nore, Nathanaël Courant <nore@mesecons.net> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef ENRICHEDSTRING_HEADER +#define ENRICHEDSTRING_HEADER + +#include <string> +#include <vector> +#include <SColor.h> + +class EnrichedString { +public: + EnrichedString(); + EnrichedString(const std::wstring &s, + const irr::video::SColor &color = irr::video::SColor(255, 255, 255, 255)); + EnrichedString(const wchar_t *str, + 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 operator=(const wchar_t *str); + void addAtEnd(const std::wstring &s, const irr::video::SColor &color); + + // Adds the character source[i] at the end. + // An EnrichedString should always be able to be copied + // to the end of an existing EnrichedString that way. + void addChar(const EnrichedString &source, size_t i); + + // Adds a single character at the end, without specifying its + // color. The color used will be the one from the last character. + void addCharNoColor(wchar_t c); + + EnrichedString substr(size_t pos = 0, size_t len = std::string::npos) const; + EnrichedString operator+(const EnrichedString &other) const; + void operator+=(const EnrichedString &other); + const wchar_t *c_str() const; + const std::vector<irr::video::SColor> &getColors() const; + const std::wstring &getString() const; + inline bool operator==(const EnrichedString &other) const + { + return (m_string == other.m_string && m_colors == other.m_colors); + } + inline bool operator!=(const EnrichedString &other) const + { + return !(*this == other); + } + inline void clear() + { + m_string.clear(); + m_colors.clear(); + m_has_background = false; + } + inline bool empty() const + { + return m_string.empty(); + } + inline size_t size() const + { + return m_string.size(); + } + inline bool hasBackground() const + { + return m_has_background; + } + inline irr::video::SColor getBackground() const + { + return m_background; + } +private: + std::wstring m_string; + std::vector<irr::video::SColor> m_colors; + bool m_has_background; + irr::video::SColor m_background; +}; + +#endif diff --git a/src/util/string.h b/src/util/string.h index 40ef3e4d3..c77c5a6f9 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -519,6 +519,38 @@ std::basic_string<T> unescape_enriched(const std::basic_string<T> &s) return output; } +template <typename T> +std::vector<std::basic_string<T> > split(const std::basic_string<T> &s, T delim) +{ + std::vector<std::basic_string<T> > tokens; + + std::basic_string<T> current; + bool last_was_escape = false; + for (size_t i = 0; i < s.length(); i++) { + T si = s[i]; + if (last_was_escape) { + current += '\\'; + current += si; + last_was_escape = false; + } else { + if (si == delim) { + tokens.push_back(current); + current = std::basic_string<T>(); + last_was_escape = false; + } else if (si == '\\') { + last_was_escape = true; + } else { + current += si; + last_was_escape = false; + } + } + } + //push last element + tokens.push_back(current); + + return tokens; +} + /** * Checks that all characters in \p to_check are a decimal digits. * |