enriched_string.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. Copyright (C) 2013 xyz, Ilya Zhuravlev <whatever@xyz.is>
  3. Copyright (C) 2016 Nore, Nathanaëlle Courant <nore@mesecons.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "enriched_string.h"
  17. #include "util/string.h"
  18. #include "debug.h"
  19. #include "log.h"
  20. using namespace irr::video;
  21. EnrichedString::EnrichedString()
  22. {
  23. clear();
  24. }
  25. EnrichedString::EnrichedString(const std::wstring &string,
  26. const std::vector<SColor> &colors)
  27. {
  28. clear();
  29. m_string = string;
  30. m_colors = colors;
  31. }
  32. EnrichedString::EnrichedString(const std::wstring &s, const SColor &color)
  33. {
  34. clear();
  35. addAtEnd(translate_string(s), color);
  36. }
  37. EnrichedString::EnrichedString(const wchar_t *str, const SColor &color)
  38. {
  39. clear();
  40. addAtEnd(translate_string(std::wstring(str)), color);
  41. }
  42. void EnrichedString::clear()
  43. {
  44. m_string.clear();
  45. m_colors.clear();
  46. m_has_background = false;
  47. m_default_length = 0;
  48. m_default_color = irr::video::SColor(255, 255, 255, 255);
  49. m_background = irr::video::SColor(0, 0, 0, 0);
  50. }
  51. EnrichedString &EnrichedString::operator=(const wchar_t *str)
  52. {
  53. clear();
  54. addAtEnd(translate_string(std::wstring(str)), m_default_color);
  55. return *this;
  56. }
  57. void EnrichedString::addAtEnd(const std::wstring &s, SColor initial_color)
  58. {
  59. SColor color(initial_color);
  60. bool use_default = (m_default_length == m_string.size() &&
  61. color == m_default_color);
  62. m_colors.reserve(m_colors.size() + s.size());
  63. size_t i = 0;
  64. while (i < s.length()) {
  65. if (s[i] != L'\x1b') {
  66. m_string += s[i];
  67. m_colors.push_back(color);
  68. ++i;
  69. continue;
  70. }
  71. ++i;
  72. size_t start_index = i;
  73. size_t length;
  74. if (i == s.length()) {
  75. break;
  76. }
  77. if (s[i] == L'(') {
  78. ++i;
  79. ++start_index;
  80. while (i < s.length() && s[i] != L')') {
  81. if (s[i] == L'\\') {
  82. ++i;
  83. }
  84. ++i;
  85. }
  86. length = i - start_index;
  87. ++i;
  88. } else {
  89. ++i;
  90. length = 1;
  91. }
  92. std::wstring escape_sequence(s, start_index, length);
  93. std::vector<std::wstring> parts = split(escape_sequence, L'@');
  94. if (parts[0] == L"c") {
  95. if (parts.size() < 2) {
  96. continue;
  97. }
  98. parseColorString(wide_to_utf8(parts[1]), color, true);
  99. // No longer use default color after first escape
  100. if (use_default) {
  101. m_default_length = m_string.size();
  102. use_default = false;
  103. }
  104. } else if (parts[0] == L"b") {
  105. if (parts.size() < 2) {
  106. continue;
  107. }
  108. parseColorString(wide_to_utf8(parts[1]), m_background, true);
  109. m_has_background = true;
  110. }
  111. }
  112. // Update if no escape character was found
  113. if (use_default)
  114. m_default_length = m_string.size();
  115. }
  116. void EnrichedString::addChar(const EnrichedString &source, size_t i)
  117. {
  118. m_string += source.m_string[i];
  119. m_colors.push_back(source.m_colors[i]);
  120. }
  121. void EnrichedString::addCharNoColor(wchar_t c)
  122. {
  123. m_string += c;
  124. if (m_colors.empty()) {
  125. m_colors.emplace_back(m_default_color);
  126. } else {
  127. m_colors.push_back(m_colors[m_colors.size() - 1]);
  128. }
  129. }
  130. EnrichedString EnrichedString::operator+(const EnrichedString &other) const
  131. {
  132. EnrichedString result = *this;
  133. result += other;
  134. return result;
  135. }
  136. void EnrichedString::operator+=(const EnrichedString &other)
  137. {
  138. bool update_default_color = m_default_length == m_string.size();
  139. m_string += other.m_string;
  140. m_colors.insert(m_colors.end(), other.m_colors.begin(), other.m_colors.end());
  141. if (update_default_color) {
  142. m_default_length += other.m_default_length;
  143. updateDefaultColor();
  144. }
  145. }
  146. EnrichedString EnrichedString::getNextLine(size_t *pos) const
  147. {
  148. size_t str_pos = *pos;
  149. // Split per line
  150. size_t str_nl = getString().find(L'\n', str_pos);
  151. if (str_nl == std::wstring::npos)
  152. str_nl = getString().size();
  153. EnrichedString line = substr(str_pos, str_nl - str_pos);
  154. str_pos += line.size() + 1;
  155. *pos = str_pos;
  156. return line;
  157. }
  158. EnrichedString EnrichedString::substr(size_t pos, size_t len) const
  159. {
  160. if (pos >= m_string.length())
  161. return EnrichedString();
  162. if (len == std::string::npos || pos + len > m_string.length())
  163. len = m_string.length() - pos;
  164. EnrichedString str(
  165. m_string.substr(pos, len),
  166. std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
  167. );
  168. str.m_has_background = m_has_background;
  169. str.m_background = m_background;
  170. if (pos < m_default_length)
  171. str.m_default_length = std::min(m_default_length - pos, str.size());
  172. str.setDefaultColor(m_default_color);
  173. return str;
  174. }
  175. const wchar_t *EnrichedString::c_str() const
  176. {
  177. return m_string.c_str();
  178. }
  179. const std::vector<SColor> &EnrichedString::getColors() const
  180. {
  181. return m_colors;
  182. }
  183. const std::wstring &EnrichedString::getString() const
  184. {
  185. return m_string;
  186. }
  187. void EnrichedString::updateDefaultColor()
  188. {
  189. sanity_check(m_default_length <= m_colors.size());
  190. for (size_t i = 0; i < m_default_length; ++i)
  191. m_colors[i] = m_default_color;
  192. }