MyGUI  3.2.2
MyGUI_TextIterator.cpp
Go to the documentation of this file.
1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_TextIterator.h"
9 
10 namespace MyGUI
11 {
12 
13  TextIterator::TextIterator() :
14  mPosition(0),
15  mSize(ITEM_NONE),
16  mFirst(true),
17  mHistory(nullptr)
18  {
19  }
20 
21  TextIterator::TextIterator(const UString& _text, VectorChangeInfo* _history) :
22  mText(_text),
23  mCurrent(mText.begin()),
24  mEnd(mText.end()),
25  mSave(mEnd),
26  mPosition(0),
27  mSize(ITEM_NONE),
28  mFirst(true),
29  mHistory(_history)
30  {
31  }
32 
34  {
35  if (mCurrent == mEnd) return false;
36  else if (mFirst)
37  {
38  mFirst = false;
39  return true;
40  }
41 
42  // ставим на следующий символ проскакивая все тэги
43  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
44  {
45 
46  if ((*iter) == L'#')
47  {
48 
49  // следующий символ
50  ++ iter;
51  if (iter == mEnd)
52  {
53  mCurrent = mEnd;
54  return false;
55  }
56 
57  // две решетки подряд
58  if ((*iter) == L'#')
59  {
60 
61  // следующий символ
62  mPosition ++;
63  ++iter;
64  if (iter == mEnd)
65  {
66  mCurrent = mEnd;
67  return false;
68  }
69 
70  // указатель на следующий символ
71  mCurrent = iter;
72  return true;
73  }
74 
75  // остальные 5 символов цвета
76  for (size_t pos = 0; pos < 5; pos++)
77  {
78  // следующий символ
79  ++ iter;
80  if (iter == mEnd)
81  {
82  mCurrent = mEnd;
83  return false;
84  }
85  }
86 
87  }
88  else
89  {
90 
91  // обыкновенный символ
92  mPosition ++;
93  ++iter;
94  if (iter == mEnd)
95  {
96  mCurrent = mEnd;
97  return false;
98  }
99 
100  // указатель на следующий символ
101  mCurrent = iter;
102  return true;
103  }
104  }
105 
106  return false;
107  }
108 
109  // возвращает цвет
110  bool TextIterator::getTagColour(UString& _colour) const
111  {
112  if (mCurrent == mEnd) return false;
113 
114  UString::iterator iter = mCurrent;
115 
116  // нам нужен последний цвет
117  bool ret = false;
118  while (getTagColour(_colour, iter))
119  {
120  ret = true;
121  }
122 
123  return ret;
124  }
125 
126  bool TextIterator::setTagColour(const Colour& _colour)
127  {
128  if (mCurrent == mEnd) return false;
129  // очищаем все цвета
130  clearTagColour();
131  // на всякий
132  if (mCurrent == mEnd) return false;
133 
134  const size_t SIZE = 16;
135  wchar_t buff[SIZE];
136 
137 #ifdef __MINGW32__
138  swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
139 #else
140  swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
141 #endif
142  // непосредственная вставка
143  UString tmpStr = UString(buff);
144  insert(mCurrent, tmpStr);
145 
146  return true;
147  }
148 
150  {
151  if (mCurrent == mEnd) return false;
152  // очищаем все цвета
153  clearTagColour();
154  // на всякий
155  if (mCurrent == mEnd) return false;
156 
157  // проверяем на цвет хоть чуть чуть
158  if ( (_colour.size() != 7) || (_colour.find(L'#', 1) != _colour.npos) ) return false;
159 
160  // непосредственная вставка
161  insert(mCurrent, _colour);
162 
163  return true;
164  }
165 
166  // возвращает размер строки
167  size_t TextIterator::getSize() const
168  {
169  if (mSize != ITEM_NONE) return mSize;
170  mSize = mPosition;
171 
172  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
173  {
174 
175  if ((*iter) == L'#')
176  {
177  // следующий символ
178  ++ iter;
179  if (iter == mEnd) break;
180 
181  // тэг цвета
182  if ((*iter) != L'#')
183  {
184  // остальные 5 символов цвета
185  for (size_t pos = 0; pos < 5; pos++)
186  {
187  ++ iter;
188  if (iter == mEnd)
189  {
190  --iter;
191  break;
192  }
193  }
194  continue;
195  }
196  }
197 
198  // обыкновенный символ
199  mSize ++;
200  }
201 
202  return mSize;
203  }
204 
205  // возвращает текст без тегов
207  {
208  UString ret;
209  ret.reserve(_text.size());
210 
211  UString::const_iterator end = _text.end();
212  for (UString::const_iterator iter = _text.begin(); iter != end; ++iter)
213  {
214 
215  if ((*iter) == L'#')
216  {
217  // следующий символ
218  ++ iter;
219  if (iter == end) break;
220 
221  // тэг цвета
222  if ((*iter) != L'#')
223  {
224  // остальные 5 символов цвета
225  for (size_t pos = 0; pos < 5; pos++)
226  {
227  ++ iter;
228  if (iter == end)
229  {
230  --iter;
231  break;
232  }
233  }
234  continue;
235  }
236  }
237 
238  // обыкновенный символ
239  ret.push_back(*iter);
240  }
241 
242  return ret;
243  }
244 
245  // возвращает цвет
246  bool TextIterator::getTagColour(UString& _colour, UString::iterator& _iter) const
247  {
248  if ( (_iter == mEnd) || ((*_iter) != L'#') ) return false;
249 
250  // следующий символ
251  ++_iter;
252  if ( (_iter == mEnd) || ((*_iter) == L'#') ) return false;
253 
254  // берем цвет
255  wchar_t buff[16] = L"#FFFFFF\0";
256  buff[1] = (wchar_t)(*_iter);
257  for (size_t pos = 2; pos < 7; pos++)
258  {
259  ++_iter;
260  if ( _iter == mEnd ) return false;
261  buff[pos] = (wchar_t)(*_iter);
262  }
263 
264  // ставим на следующий тег или символ
265  ++_iter;
266 
267  // возвращаем цвет
268  _colour = buff;
269  return true;
270  }
271 
273  {
274  for (UString::iterator iter = _text.begin(); iter != _text.end(); ++iter)
275  {
276  if ( ((*iter) == FontCodeType::NEL) ||
277  ((*iter) == FontCodeType::CR) ||
278  ((*iter) == FontCodeType::LF) )
279  {
280  (*iter) = FontCodeType::Space;
281  }
282  }
283  }
284 
286  {
287  if (mCurrent == mEnd) return false;
288  mSave = mCurrent;
289  return true;
290  }
291 
293  {
294  if (mSave == mEnd) return L"";
295  size_t start = mSave - mText.begin();
296  return mText.substr(start, mCurrent - mText.begin() - start);
297  }
298 
300  {
301  if (mSave == mEnd) return false;
302  mCurrent = erase(mSave, mCurrent);
303  mSave = mEnd = mText.end();
304  return true;
305  }
306 
307  void TextIterator::insertText(const UString& _insert, bool _multiLine)
308  {
309  UString text = _insert;
310 
311  // нормализуем
312  normaliseNewLine(text);
313 
314  if (!_multiLine)
315  clearNewLine(text);
316 
317  insert(mCurrent, text);
318  }
319 
320  void TextIterator::setText(const UString& _text, bool _multiLine)
321  {
322  // сначала все очищаем
323  clear();
324 
325  // а теперь вставляем
326  UString text = _text;
327 
328  // нормализуем
329  normaliseNewLine(text);
330 
331  if (!_multiLine)
332  clearNewLine(text);
333 
334  insert(mCurrent, text);
335  }
336 
338  {
339  if (_char == L'#') return L"##";
340  wchar_t buff[16] = L"_\0";
341  buff[0] = (wchar_t)_char;
342  return buff;
343  }
344 
346  {
347  const size_t SIZE = 16;
348  wchar_t buff[SIZE];
349 //FIXME
350 #ifdef __MINGW32__
351  swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
352 #else
353  swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
354 #endif
355  return buff;
356  }
357 
359  {
360  // преобразуем в строку с тегами
361  UString text(_text);
362  for (UString::iterator iter = text.begin(); iter != text.end(); ++iter)
363  {
364  // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
365  if (L'#' == (*iter)) iter = text.insert(++iter, L'#');
366  }
367  return text;
368  }
369 
370  void TextIterator::insert(UString::iterator& _start, UString& _insert)
371  {
372  // сбрасываем размер
373  mSize = ITEM_NONE;
374  // записываем в историю
375  if (mHistory) mHistory->push_back(TextCommandInfo(_insert, _start - mText.begin(), TextCommandInfo::COMMAND_INSERT));
376  // запоминаем позицию итератора
377  size_t pos = _start - mText.begin();
378  size_t pos_save = (mSave == mEnd) ? ITEM_NONE : _start - mText.begin();
379  // непосредственно вставляем
380  mText.insert(_start, _insert.begin(), _insert.end());
381  // возвращаем итераторы
382  _start = mText.begin() + pos;
383  mEnd = mText.end();
384  (pos_save == ITEM_NONE) ? mSave = mEnd : mSave = mText.begin() + pos_save;
385  }
386 
387  UString::iterator TextIterator::erase(UString::iterator _start, UString::iterator _end)
388  {
389  // сбрасываем размер
390  mSize = ITEM_NONE;
391  // сохраняем в историю
392  size_t start = _start - mText.begin();
393  if (mHistory) mHistory->push_back(TextCommandInfo(mText.substr(start, _end - _start), start, TextCommandInfo::COMMAND_ERASE));
394  // возвращаем итератор
395  return mText.erase(_start, _end);
396  }
397 
398  void TextIterator::clear()
399  {
400  if (mText.empty()) return;
401 
402  // записываем в историю
403  if (mHistory) mHistory->push_back(TextCommandInfo(mText, 0, TextCommandInfo::COMMAND_ERASE));
404 
405  // все сбрасываем
406  mText.clear();
407  mCurrent = mText.begin();
408  mEnd = mSave = mText.end();
409  mSize = ITEM_NONE;
410  }
411 
412  void TextIterator::cutMaxLength(size_t _max)
413  {
414  if ( (mSize != ITEM_NONE) && (mSize <= _max) ) return;
415  if (mPosition > _max)
416  {
417  // придется считать сначала
418  mSize = mPosition = 0;
419  mCurrent = mText.begin();
420  mEnd = mSave = mText.end();
421  }
422 
423  mSize = mPosition;
424 
425  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
426  {
427 
428  if ((*iter) == L'#')
429  {
430  // следующий символ
431  ++ iter;
432  if (iter == mEnd) break;
433 
434  // тэг цвета
435  if ((*iter) != L'#')
436  {
437  // остальные 5 символов цвета
438  for (size_t pos = 0; pos < 5; pos++)
439  {
440  ++ iter;
441  if (iter == mEnd)
442  {
443  -- iter;
444  break;
445  }
446  }
447  continue;
448  }
449  }
450 
451  // проверяем и обрезаем
452  if (mSize == _max)
453  {
454  mPosition = mSize; // сохраняем
455  mCurrent = erase(iter, mEnd);
456  mSave = mEnd = mText.end();
457  mSize = mPosition; // восстанавливаем
458  return;
459  }
460 
461  // увеличиваем
462  mSize ++;
463  }
464  }
465 
467  {
468  // узнаем размер без тегов
469  size_t size = getSize();
470  if (size <= _max) return;
471 
472  // разница
473  size_t diff = size - _max;
474 
475  // последний цвет
476  UString::iterator iter_colour = mEnd;
477 
478  // теперь пройдем от начала и узнаем реальную позицию разницы
479  UString::iterator iter = mText.begin();
480  for (; iter != mEnd; ++iter)
481  {
482  if ((*iter) == L'#')
483  {
484  UString::iterator save = iter;
485 
486  // следующий символ
487  ++ iter;
488  if (iter == mEnd) break;
489 
490  // тэг цвета
491  if ((*iter) != L'#')
492  {
493  // остальные 5 символов цвета
494  for (size_t pos = 0; pos < 5; pos++)
495  {
496  ++ iter;
497  if (iter == mEnd)
498  {
499  -- iter;
500  break;
501  }
502  }
503  // сохраняем цвет
504  iter_colour = save;
505  }
506  continue;
507  }
508  // обычный символ был
509  if (diff == 0) break;
510  -- diff;
511  }
512 
513  UString colour;
514  // если бы цвет, то вставляем назад
515  if (iter_colour != mEnd)
516  {
517  colour.append(iter_colour, iter_colour + size_t(7));
518  }
519 
520  mCurrent = erase(mText.begin(), iter);
521  mEnd = mText.end();
522  mSave = mText.end(); //FIXME
523  mPosition = 0;
524  mSize = _max;
525 
526  if ( ! colour.empty() ) setTagColour(colour);
527 
528  }
529 
531  {
532  if (mCurrent == mEnd) return;
533 
534  UString::iterator iter = mCurrent;
535  UString colour;
536  // нам нужен последний цвет
537  while (getTagColour(colour, iter))
538  {
539  // обязательно обновляем итераторы
540  iter = mCurrent = erase(mCurrent, iter);
541  mEnd = mText.end();
542  }
543  }
544 
546  {
547  return mPosition;
548  }
549 
551  {
552  return mText;
553  }
554 
556  {
557  clear();
558  }
559 
561  {
562  return L"\n";
563  }
564 
565  void TextIterator::normaliseNewLine(UString& _text)
566  {
567  for (size_t index = 0; index < _text.size(); ++index)
568  {
569  Char character = _text[index];
570  if ((character == FontCodeType::CR) &&
571  ((index + 1) < _text.size()) &&
572  (_text[index + 1] == FontCodeType::LF))
573  {
574  _text.erase(index, 1);
575  }
576  }
577  }
578 
579 } // namespace MyGUI
static UString getTextCharInfo(Char _char)
bool empty() const
returns true if the string has no elements, false otherwise
void clearNewLine(UString &_text)
UString & append(const UString &str)
appends str on to the end of the current string
void cutMaxLength(size_t _max)
std::vector< TextCommandInfo > VectorChangeInfo
static UString getOnlyText(const UString &_text)
iterator erase(iterator loc)
removes the code point pointed to by loc, returning an iterator to the next character
const UString & getText() const
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:17
static const size_type npos
the usual constant representing: not found, no limit, etc
const forward iterator for UString
#define nullptr
void push_back(unicode_char val)
appends val to the end of the string
void clear()
deletes all of the elements in the string
iterator begin()
returns an iterator to the first element of the string
_fwd_iterator iterator
iterator
void insertText(const UString &_insert, bool _multiLine)
static UString toTagsString(const UString &_text)
size_type find(const UString &str, size_type index=0) const
returns the index of the first occurrence of str within the current string, starting at index; return...
unsigned int Char
Definition: MyGUI_Types.h:51
void reserve(size_type size)
sets the capacity of the string to at least size code points
forward iterator for UString
void setText(const UString &_text, bool _multiLine)
bool setTagColour(const Colour &_colour)
size_type size() const
Returns the number of code points in the current string.
static UString getTextNewLine()
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
void cutMaxLengthFromBeginning(size_t _max)
iterator insert(iterator i, const code_point &ch)
inserts ch before the code point denoted by i
iterator end()
returns an iterator just past the end of the string
UString substr(size_type index, size_type num=npos) const
returns a substring of the current string, starting at index, and num characters long.
bool getTagColour(UString &_colour) const
static UString convertTagColour(const Colour &_colour)