From 14ef2b445adcec770defe1abf83af9d22ccf39d8 Mon Sep 17 00:00:00 2001 From: Ekdohibs Date: Tue, 31 May 2016 17:30:11 +0200 Subject: Add colored text (not only colored chat). Add documentation, move files to a proper place and avoid memory leaks. Make it work with most kind of texts, and allow backgrounds too. --- src/util/CMakeLists.txt | 11 +- src/util/coloredstring.cpp | 68 ----- src/util/coloredstring.h | 44 --- src/util/enriched_string.cpp | 166 +++++++++++ src/util/enriched_string.h | 91 ++++++ src/util/statictext.cpp | 654 ------------------------------------------- src/util/statictext.h | 150 ---------- src/util/string.h | 32 +++ 8 files changed, 290 insertions(+), 926 deletions(-) delete mode 100644 src/util/coloredstring.cpp delete mode 100644 src/util/coloredstring.h create mode 100644 src/util/enriched_string.cpp create mode 100644 src/util/enriched_string.h delete mode 100644 src/util/statictext.cpp delete mode 100644 src/util/statictext.h (limited to 'src/util') 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 - -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 &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(m_colors.begin() + pos, m_colors.end()) - ); - } else { - return ColoredString( - m_string.substr(pos, len), - std::vector(m_colors.begin() + pos, m_colors.begin() + pos + len) - ); - } -} - -const wchar_t *ColoredString::c_str() const { - return m_string.c_str(); -} - -const std::vector &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 - -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 -#include -#include - -using namespace irr::video; - -class ColoredString { -public: - ColoredString(); - ColoredString(const std::wstring &s); - ColoredString(const std::wstring &string, const std::vector &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 &getColors() const; - const std::wstring &getString() const; -private: - std::wstring m_string; - std::vector 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 +Copyright (C) 2016 Nore, Nathanaƫl Courant + +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 &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 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 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(m_colors.begin() + pos, m_colors.end()) + ); + } else { + return EnrichedString( + m_string.substr(pos, len), + std::vector(m_colors.begin() + pos, m_colors.begin() + pos + len) + ); + } +} + +const wchar_t *EnrichedString::c_str() const +{ + return m_string.c_str(); +} + +const std::vector &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 +Copyright (C) 2016 Nore, Nathanaƫl Courant + +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 +#include +#include + +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 &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 &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 m_colors; + bool m_has_background; + irr::video::SColor m_background; +}; + +#endif diff --git a/src/util/statictext.cpp b/src/util/statictext.cpp deleted file mode 100644 index b534b560e..000000000 --- a/src/util/statictext.cpp +++ /dev/null @@ -1,654 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "statictext.h" -#ifdef _IRR_COMPILE_WITH_GUI_ - -//Only compile this if freetype is enabled. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cguittfont/xCGUITTFont.h" -#include "util/string.h" - -namespace irr -{ -namespace gui -{ -//! constructor -StaticText::StaticText(const wchar_t* text, bool border, - IGUIEnvironment* environment, IGUIElement* parent, - s32 id, const core::rect& rectangle, - bool background) -: IGUIStaticText(environment, parent, id, rectangle), - HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT), - Border(border), OverrideColorEnabled(false), OverrideBGColorEnabled(false), WordWrap(false), Background(background), - RestrainTextInside(true), RightToLeft(false), - OverrideColor(video::SColor(101,255,255,255)), BGColor(video::SColor(101,210,210,210)), - OverrideFont(0), LastBreakFont(0) -{ - #ifdef _DEBUG - setDebugName("StaticText"); - #endif - - Text = text; - if (environment && environment->getSkin()) - { - BGColor = environment->getSkin()->getColor(gui::EGDC_3D_FACE); - } -} - - -//! destructor -StaticText::~StaticText() -{ - if (OverrideFont) - OverrideFont->drop(); -} - - -//! draws the element and its children -void StaticText::draw() -{ - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - video::IVideoDriver* driver = Environment->getVideoDriver(); - - core::rect frameRect(AbsoluteRect); - - // draw background - - if (Background) - { - if ( !OverrideBGColorEnabled ) // skin-colors can change - BGColor = skin->getColor(gui::EGDC_3D_FACE); - - driver->draw2DRectangle(BGColor, frameRect, &AbsoluteClippingRect); - } - - // draw the border - - if (Border) - { - skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect); - frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); - } - - // draw the text - if (Text.size()) - { - IGUIFont* font = getActiveFont(); - - if (font) - { - if (!WordWrap) - { - // TODO: add colors here - if (VAlign == EGUIA_LOWERRIGHT) - { - frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - - font->getDimension(L"A").Height - font->getKerningHeight(); - } - if (HAlign == EGUIA_LOWERRIGHT) - { - frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - - font->getDimension(Text.c_str()).Width; - } - - font->draw(Text.c_str(), frameRect, - OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), - HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); - } - else - { - if (font != LastBreakFont) - breakText(); - - core::rect r = frameRect; - s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); - s32 totalHeight = height * BrokenText.size(); - if (VAlign == EGUIA_CENTER) - { - r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2); - } - else if (VAlign == EGUIA_LOWERRIGHT) - { - r.UpperLeftCorner.Y = r.LowerRightCorner.Y - totalHeight; - } - - irr::video::SColor previous_color(255, 255, 255, 255); - for (u32 i=0; igetDimension(BrokenText[i].c_str()).Width; - } - - std::vector colors; - std::wstring str; - - str = colorizeText(BrokenText[i].c_str(), colors, previous_color); - if (!colors.empty()) - previous_color = colors[colors.size() - 1]; - - irr::gui::CGUITTFont *tmp = static_cast(font); - tmp->draw(str.c_str(), r, - colors, - HAlign == EGUIA_CENTER, false, (RestrainTextInside ? &AbsoluteClippingRect : NULL)); - - r.LowerRightCorner.Y += height; - r.UpperLeftCorner.Y += height; - } - } - } - } - - IGUIElement::draw(); -} - - -//! Sets another skin independent font. -void StaticText::setOverrideFont(IGUIFont* font) -{ - if (OverrideFont == font) - return; - - if (OverrideFont) - OverrideFont->drop(); - - OverrideFont = font; - - if (OverrideFont) - OverrideFont->grab(); - - breakText(); -} - -//! Gets the override font (if any) -IGUIFont * StaticText::getOverrideFont() const -{ - return OverrideFont; -} - -//! Get the font which is used right now for drawing -IGUIFont* StaticText::getActiveFont() const -{ - if ( OverrideFont ) - return OverrideFont; - IGUISkin* skin = Environment->getSkin(); - if (skin) - return skin->getFont(); - return 0; -} - -//! Sets another color for the text. -void StaticText::setOverrideColor(video::SColor color) -{ - OverrideColor = color; - OverrideColorEnabled = true; -} - - -//! Sets another color for the text. -void StaticText::setBackgroundColor(video::SColor color) -{ - BGColor = color; - OverrideBGColorEnabled = true; - Background = true; -} - - -//! Sets whether to draw the background -void StaticText::setDrawBackground(bool draw) -{ - Background = draw; -} - - -//! Gets the background color -video::SColor StaticText::getBackgroundColor() const -{ - return BGColor; -} - - -//! Checks if background drawing is enabled -bool StaticText::isDrawBackgroundEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Background; -} - - -//! Sets whether to draw the border -void StaticText::setDrawBorder(bool draw) -{ - Border = draw; -} - - -//! Checks if border drawing is enabled -bool StaticText::isDrawBorderEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return Border; -} - - -void StaticText::setTextRestrainedInside(bool restrainTextInside) -{ - RestrainTextInside = restrainTextInside; -} - - -bool StaticText::isTextRestrainedInside() const -{ - return RestrainTextInside; -} - - -void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) -{ - HAlign = horizontal; - VAlign = vertical; -} - - -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 -const video::SColor& StaticText::getOverrideColor() const -#else -video::SColor StaticText::getOverrideColor() const -#endif -{ - return OverrideColor; -} - - -//! Sets if the static text should use the overide color or the -//! color in the gui skin. -void StaticText::enableOverrideColor(bool enable) -{ - OverrideColorEnabled = enable; -} - - -bool StaticText::isOverrideColorEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return OverrideColorEnabled; -} - - -//! Enables or disables word wrap for using the static text as -//! multiline text control. -void StaticText::setWordWrap(bool enable) -{ - WordWrap = enable; - breakText(); -} - - -bool StaticText::isWordWrapEnabled() const -{ - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return WordWrap; -} - - -void StaticText::setRightToLeft(bool rtl) -{ - if (RightToLeft != rtl) - { - RightToLeft = rtl; - breakText(); - } -} - - -bool StaticText::isRightToLeft() const -{ - return RightToLeft; -} - - -//! Breaks the single text line. -void StaticText::breakText() -{ - if (!WordWrap) - return; - - BrokenText.clear(); - - IGUISkin* skin = Environment->getSkin(); - IGUIFont* font = getActiveFont(); - if (!font) - return; - - LastBreakFont = font; - - core::stringw line; - core::stringw word; - core::stringw whitespace; - s32 size = Text.size(); - s32 length = 0; - s32 elWidth = RelativeRect.getWidth(); - if (Border) - elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X); - wchar_t c; - - std::vector 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 - // some order and boundaries which change. - if (!RightToLeft) - { - // regular (left-to-right) - for (s32 i=0; igetDimension(whitespace.c_str()).Width; - const std::wstring sanitized = removeEscapes(word.c_str()); - const s32 wordlgth = font->getDimension(sanitized.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) ); - 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"-"); - const s32 secondLength = font->getDimension(second.c_str()).Width; - - length = secondLength; - line = second; - } - else - { - // No soft hyphen found, so there's nothing more we can do - // break to next line - if (length) - BrokenText.push_back(line); - length = wordlgth; - line = word; - } - } - else if (length && (length + wordlgth + whitelgth > elWidth)) - { - // break to next line - BrokenText.push_back(line); - length = wordlgth; - line = word; - } - else - { - // add word to line - line += whitespace; - line += word; - length += whitelgth + wordlgth; - } - - word = L""; - whitespace = L""; - } - - if ( isWhitespace ) - { - whitespace += c; - } - - // compute line break - if (lineBreak) - { - line += whitespace; - line += word; - BrokenText.push_back(line); - line = L""; - word = L""; - whitespace = L""; - length = 0; - } - } - } - - line += whitespace; - line += word; - BrokenText.push_back(line); - } - else - { - // right-to-left - for (s32 i=size; i>=0; --i) - { - c = Text[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; - } - c = '\0'; - } - else if (c == L'\n') // Unix breaks - { - lineBreak = true; - c = '\0'; - } - - if (c==L' ' || c==0 || i==0) - { - if (word.size()) - { - // 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 s32 wordlgth = font->getDimension(word.c_str()).Width; - - if (length && (length + wordlgth + whitelgth > elWidth)) - { - // break to next line - BrokenText.push_back(line); - length = wordlgth; - line = word; - } - else - { - // add word to line - line = whitespace + line; - line = word + line; - length += whitelgth + wordlgth; - } - - word = L""; - whitespace = L""; - } - - if (c != 0) - whitespace = core::stringw(&c, 1) + whitespace; - - // compute line break - if (lineBreak) - { - line = whitespace + line; - line = word + line; - BrokenText.push_back(line); - line = L""; - word = L""; - whitespace = L""; - length = 0; - } - } - else - { - // yippee this is a word.. - word = core::stringw(&c, 1) + word; - } - } - - line = whitespace + line; - line = word + line; - BrokenText.push_back(line); - } -} - - -//! Sets the new caption of this element. -void StaticText::setText(const wchar_t* text) -{ - IGUIElement::setText(text); - breakText(); -} - - -void StaticText::updateAbsolutePosition() -{ - IGUIElement::updateAbsolutePosition(); - breakText(); -} - - -//! Returns the height of the text in pixels when it is drawn. -s32 StaticText::getTextHeight() const -{ - IGUIFont* font = getActiveFont(); - if (!font) - return 0; - - s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); - - if (WordWrap) - height *= BrokenText.size(); - - return height; -} - - -s32 StaticText::getTextWidth() const -{ - IGUIFont * font = getActiveFont(); - if(!font) - return 0; - - if(WordWrap) - { - s32 widest = 0; - - for(u32 line = 0; line < BrokenText.size(); ++line) - { - s32 width = font->getDimension(BrokenText[line].c_str()).Width; - - if(width > widest) - widest = width; - } - - return widest; - } - else - { - return font->getDimension(Text.c_str()).Width; - } -} - - -//! Writes attributes of the element. -//! Implement this to expose the attributes of your element for -//! scripting languages, editors, debuggers or xml serialization purposes. -void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const -{ - IGUIStaticText::serializeAttributes(out,options); - - out->addBool ("Border", Border); - out->addBool ("OverrideColorEnabled",OverrideColorEnabled); - out->addBool ("OverrideBGColorEnabled",OverrideBGColorEnabled); - out->addBool ("WordWrap", WordWrap); - out->addBool ("Background", Background); - out->addBool ("RightToLeft", RightToLeft); - out->addBool ("RestrainTextInside", RestrainTextInside); - out->addColor ("OverrideColor", OverrideColor); - out->addColor ("BGColor", BGColor); - out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); - out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); - - // out->addFont ("OverrideFont", OverrideFont); -} - - -//! Reads attributes of the element -void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) -{ - IGUIStaticText::deserializeAttributes(in,options); - - Border = in->getAttributeAsBool("Border"); - enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); - OverrideBGColorEnabled = in->getAttributeAsBool("OverrideBGColorEnabled"); - setWordWrap(in->getAttributeAsBool("WordWrap")); - Background = in->getAttributeAsBool("Background"); - RightToLeft = in->getAttributeAsBool("RightToLeft"); - RestrainTextInside = in->getAttributeAsBool("RestrainTextInside"); - OverrideColor = in->getAttributeAsColor("OverrideColor"); - BGColor = in->getAttributeAsColor("BGColor"); - - setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), - (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); - - // OverrideFont = in->getAttributeAsFont("OverrideFont"); -} - -} // end namespace gui -} // end namespace irr - - -#endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/util/statictext.h b/src/util/statictext.h deleted file mode 100644 index 8d2f879e7..000000000 --- a/src/util/statictext.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __C_GUI_STATIC_TEXT_H_INCLUDED__ -#define __C_GUI_STATIC_TEXT_H_INCLUDED__ - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_GUI_ - -#include "IGUIStaticText.h" -#include "irrArray.h" - -#include - -namespace irr -{ -namespace gui -{ - class StaticText : public IGUIStaticText - { - public: - - //! constructor - StaticText(const wchar_t* text, bool border, IGUIEnvironment* environment, - IGUIElement* parent, s32 id, const core::rect& rectangle, - bool background = false); - - //! destructor - virtual ~StaticText(); - - //! draws the element and its children - virtual void draw(); - - //! Sets another skin independent font. - virtual void setOverrideFont(IGUIFont* font=0); - - //! Gets the override font (if any) - virtual IGUIFont* getOverrideFont() const; - - //! Get the font which is used right now for drawing - virtual IGUIFont* getActiveFont() const; - - //! Sets another color for the text. - virtual void setOverrideColor(video::SColor color); - - //! Sets another color for the background. - virtual void setBackgroundColor(video::SColor color); - - //! Sets whether to draw the background - virtual void setDrawBackground(bool draw); - - //! Gets the background color - virtual video::SColor getBackgroundColor() const; - - //! Checks if background drawing is enabled - virtual bool isDrawBackgroundEnabled() const; - - //! Sets whether to draw the border - virtual void setDrawBorder(bool draw); - - //! Checks if border drawing is enabled - virtual bool isDrawBorderEnabled() const; - - //! Sets alignment mode for text - virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); - - //! Gets the override color - #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 - virtual const video::SColor& getOverrideColor() const; - #else - virtual video::SColor getOverrideColor() const; - #endif - - //! Sets if the static text should use the overide color or the - //! color in the gui skin. - virtual void enableOverrideColor(bool enable); - - //! Checks if an override color is enabled - virtual bool isOverrideColorEnabled() const; - - //! Set whether the text in this label should be clipped if it goes outside bounds - virtual void setTextRestrainedInside(bool restrainedInside); - - //! Checks if the text in this label should be clipped if it goes outside bounds - virtual bool isTextRestrainedInside() const; - - //! Enables or disables word wrap for using the static text as - //! multiline text control. - virtual void setWordWrap(bool enable); - - //! Checks if word wrap is enabled - virtual bool isWordWrapEnabled() const; - - //! Sets the new caption of this element. - virtual void setText(const wchar_t* text); - - //! Returns the height of the text in pixels when it is drawn. - virtual s32 getTextHeight() const; - - //! Returns the width of the current text, in the current font - virtual s32 getTextWidth() const; - - //! Updates the absolute position, splits text if word wrap is enabled - virtual void updateAbsolutePosition(); - - //! Set whether the string should be interpreted as right-to-left (RTL) text - /** \note This component does not implement the Unicode bidi standard, the - text of the component should be already RTL if you call this. The - main difference when RTL is enabled is that the linebreaks for multiline - elements are performed starting from the end. - */ - virtual void setRightToLeft(bool rtl); - - //! Checks if the text should be interpreted as right-to-left text - virtual bool isRightToLeft() const; - - //! Writes attributes of the element. - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; - - //! Reads attributes of the element - virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); - - private: - - //! Breaks the single text line. - void breakText(); - - EGUI_ALIGNMENT HAlign, VAlign; - bool Border; - bool OverrideColorEnabled; - bool OverrideBGColorEnabled; - bool WordWrap; - bool Background; - bool RestrainTextInside; - bool RightToLeft; - - video::SColor OverrideColor, BGColor; - gui::IGUIFont* OverrideFont; - gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated. - - core::array< core::stringw > BrokenText; - }; - -} // end namespace gui -} // end namespace irr - -#endif // _IRR_COMPILE_WITH_GUI_ - -#endif // C_GUI_STATIC_TEXT_H_INCLUDED 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 unescape_enriched(const std::basic_string &s) return output; } +template +std::vector > split(const std::basic_string &s, T delim) +{ + std::vector > tokens; + + std::basic_string 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(); + 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. * -- cgit v1.2.3