enriched_string.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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(std::wstring_view string,
  26. const std::vector<SColor> &colors)
  27. {
  28. clear();
  29. m_string = string;
  30. m_colors = colors;
  31. }
  32. EnrichedString::EnrichedString(std::wstring_view s, const SColor &color)
  33. {
  34. clear();
  35. addAtEnd(translate_string(s), color);
  36. }
  37. void EnrichedString::clear()
  38. {
  39. m_string.clear();
  40. m_colors.clear();
  41. m_has_background = false;
  42. m_default_length = 0;
  43. m_default_color = irr::video::SColor(255, 255, 255, 255);
  44. m_background = irr::video::SColor(0, 0, 0, 0);
  45. }
  46. EnrichedString &EnrichedString::operator=(std::wstring_view str)
  47. {
  48. clear();
  49. addAtEnd(translate_string(str), m_default_color);
  50. return *this;
  51. }
  52. void EnrichedString::addAtEnd(std::wstring_view s, SColor initial_color)
  53. {
  54. SColor color(initial_color);
  55. bool use_default = (m_default_length == m_string.size() &&
  56. color == m_default_color);
  57. m_string.reserve(m_string.size() + s.size());
  58. m_colors.reserve(m_colors.size() + s.size());
  59. size_t i = 0;
  60. while (i < s.length()) {
  61. if (s[i] != L'\x1b') {
  62. m_string += s[i];
  63. m_colors.push_back(color);
  64. ++i;
  65. continue;
  66. }
  67. ++i;
  68. size_t start_index = i;
  69. size_t length;
  70. if (i == s.length()) {
  71. break;
  72. }
  73. if (s[i] == L'(') {
  74. ++i;
  75. ++start_index;
  76. while (i < s.length() && s[i] != L')') {
  77. if (s[i] == L'\\') {
  78. ++i;
  79. }
  80. ++i;
  81. }
  82. length = i - start_index;
  83. ++i;
  84. } else {
  85. ++i;
  86. length = 1;
  87. }
  88. std::wstring escape_sequence(s, start_index, length);
  89. std::vector<std::wstring> parts = split(escape_sequence, L'@');
  90. if (parts[0] == L"c") {
  91. if (parts.size() < 2) {
  92. continue;
  93. }
  94. parseColorString(wide_to_utf8(parts[1]), color, true);
  95. // No longer use default color after first escape
  96. if (use_default) {
  97. m_default_length = m_string.size();
  98. use_default = false;
  99. }
  100. } else if (parts[0] == L"b") {
  101. if (parts.size() < 2) {
  102. continue;
  103. }
  104. parseColorString(wide_to_utf8(parts[1]), m_background, true);
  105. m_has_background = true;
  106. }
  107. }
  108. // Update if no escape character was found
  109. if (use_default)
  110. m_default_length = m_string.size();
  111. }
  112. void EnrichedString::addChar(const EnrichedString &source, size_t i)
  113. {
  114. m_string += source.m_string[i];
  115. m_colors.push_back(source.m_colors[i]);
  116. }
  117. void EnrichedString::addCharNoColor(wchar_t c)
  118. {
  119. m_string += c;
  120. if (m_colors.empty()) {
  121. m_colors.emplace_back(m_default_color);
  122. } else {
  123. m_colors.push_back(m_colors.back());
  124. }
  125. }
  126. EnrichedString EnrichedString::operator+(const EnrichedString &other) const
  127. {
  128. EnrichedString result = *this;
  129. result += other;
  130. return result;
  131. }
  132. void EnrichedString::operator+=(const EnrichedString &other)
  133. {
  134. bool update_default_color = m_default_length == m_string.size();
  135. m_string += other.m_string;
  136. m_colors.insert(m_colors.end(), other.m_colors.begin(), other.m_colors.end());
  137. if (update_default_color) {
  138. m_default_length += other.m_default_length;
  139. updateDefaultColor();
  140. }
  141. }
  142. EnrichedString EnrichedString::getNextLine(size_t *pos) const
  143. {
  144. size_t str_pos = *pos;
  145. // Split per line
  146. size_t str_nl = getString().find(L'\n', str_pos);
  147. if (str_nl == std::wstring::npos)
  148. str_nl = getString().size();
  149. EnrichedString line = substr(str_pos, str_nl - str_pos);
  150. str_pos += line.size() + 1;
  151. *pos = str_pos;
  152. return line;
  153. }
  154. EnrichedString EnrichedString::substr(size_t pos, size_t len) const
  155. {
  156. if (pos >= m_string.length())
  157. return EnrichedString();
  158. if (len == std::string::npos || pos + len > m_string.length())
  159. len = m_string.length() - pos;
  160. EnrichedString str(
  161. m_string.substr(pos, len),
  162. std::vector<SColor>(m_colors.begin() + pos, m_colors.begin() + pos + len)
  163. );
  164. str.m_has_background = m_has_background;
  165. str.m_background = m_background;
  166. if (pos < m_default_length)
  167. str.m_default_length = std::min(m_default_length - pos, str.size());
  168. str.setDefaultColor(m_default_color);
  169. return str;
  170. }
  171. const std::vector<SColor> &EnrichedString::getColors() const
  172. {
  173. return m_colors;
  174. }
  175. const std::wstring &EnrichedString::getString() const
  176. {
  177. return m_string;
  178. }
  179. void EnrichedString::updateDefaultColor()
  180. {
  181. sanity_check(m_default_length <= m_colors.size());
  182. for (size_t i = 0; i < m_default_length; ++i)
  183. m_colors[i] = m_default_color;
  184. }