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
MyGUI::TextCommandInfo::COMMAND_INSERT
@ COMMAND_INSERT
Definition: MyGUI_TextChangeHistory.h:25
MyGUI::TextIterator::insertText
void insertText(const UString &_insert, bool _multiLine)
Definition: MyGUI_TextIterator.cpp:307
MyGUI::VectorChangeInfo
std::vector< TextCommandInfo > VectorChangeInfo
Definition: MyGUI_TextChangeHistory.h:60
MyGUI::TextIterator::getText
const UString & getText() const
Definition: MyGUI_TextIterator.cpp:550
MyGUI::UString::push_back
void push_back(unicode_char val)
appends val to the end of the string
Definition: MyGUI_UString.cpp:661
MyGUI::TextIterator::cutMaxLength
void cutMaxLength(size_t _max)
Definition: MyGUI_TextIterator.cpp:412
MyGUI::TextIterator::setTagColour
bool setTagColour(const Colour &_colour)
Definition: MyGUI_TextIterator.cpp:126
MyGUI::TextIterator::getSize
size_t getSize() const
Definition: MyGUI_TextIterator.cpp:167
MyGUI::TextIterator::clearTagColour
void clearTagColour()
Definition: MyGUI_TextIterator.cpp:530
MyGUI::TextIterator::getTextCharInfo
static UString getTextCharInfo(Char _char)
Definition: MyGUI_TextIterator.cpp:337
MyGUI::TextIterator::getTagColour
bool getTagColour(UString &_colour) const
Definition: MyGUI_TextIterator.cpp:110
MyGUI::Colour::red
float red
Definition: MyGUI_Colour.h:49
MyGUI::ITEM_NONE
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:17
MyGUI::UString::erase
iterator erase(iterator loc)
removes the code point pointed to by loc, returning an iterator to the next character
Definition: MyGUI_UString.cpp:1164
MyGUI::UString::begin
iterator begin()
returns an iterator to the first element of the string
Definition: MyGUI_UString.cpp:787
MyGUI::UString::append
UString & append(const UString &str)
appends str on to the end of the current string
Definition: MyGUI_UString.cpp:974
MyGUI::TextIterator::getTextNewLine
static UString getTextNewLine()
Definition: MyGUI_TextIterator.cpp:560
MyGUI::TextIterator::cutMaxLengthFromBeginning
void cutMaxLengthFromBeginning(size_t _max)
Definition: MyGUI_TextIterator.cpp:466
MyGUI::TextIterator::moveNext
bool moveNext()
Definition: MyGUI_TextIterator.cpp:33
MyGUI::TextIterator::clearText
void clearText()
Definition: MyGUI_TextIterator.cpp:555
MyGUI::FontCodeType::CR
@ CR
Definition: MyGUI_FontData.h:22
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition: MyGUI_UString.h:168
MyGUI_Precompiled.h
MyGUI::UString::_const_fwd_iterator
const forward iterator for UString
Definition: MyGUI_UString.h:289
MyGUI::UString::iterator
_fwd_iterator iterator
iterator
Definition: MyGUI_UString.h:432
MyGUI::UString::_fwd_iterator
forward iterator for UString
Definition: MyGUI_UString.h:243
MyGUI::UString::npos
static const size_type npos
the usual constant representing: not found, no limit, etc
Definition: MyGUI_UString.h:187
MyGUI::TextIterator::saveStartPoint
bool saveStartPoint()
Definition: MyGUI_TextIterator.cpp:285
MyGUI::FontCodeType::Space
@ Space
Definition: MyGUI_FontData.h:23
MyGUI::UString::clear
void clear()
deletes all of the elements in the string
Definition: MyGUI_UString.cpp:647
MyGUI::TextIterator::getOnlyText
static UString getOnlyText(const UString &_text)
Definition: MyGUI_TextIterator.cpp:206
MyGUI::TextIterator::getPosition
size_t getPosition() const
Definition: MyGUI_TextIterator.cpp:545
MyGUI::TextIterator::clearNewLine
void clearNewLine(UString &_text)
Definition: MyGUI_TextIterator.cpp:272
MyGUI::Colour::green
float green
Definition: MyGUI_Colour.h:50
MyGUI::UString::find
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...
Definition: MyGUI_UString.cpp:1270
MyGUI::TextIterator::getFromStart
UString getFromStart()
Definition: MyGUI_TextIterator.cpp:292
MyGUI::TextCommandInfo::COMMAND_ERASE
@ COMMAND_ERASE
Definition: MyGUI_TextChangeHistory.h:26
nullptr
#define nullptr
Definition: MyGUI_Prerequest.h:29
MyGUI::UString::size
size_type size() const
Returns the number of code points in the current string.
Definition: MyGUI_UString.cpp:586
MyGUI::UString::reserve
void reserve(size_type size)
sets the capacity of the string to at least size code points
Definition: MyGUI_UString.cpp:612
MyGUI::Colour
Definition: MyGUI_Colour.h:17
MyGUI::Char
unsigned int Char
Definition: MyGUI_Types.h:51
MyGUI::Colour::blue
float blue
Definition: MyGUI_Colour.h:51
MyGUI::UString::empty
bool empty() const
returns true if the string has no elements, false otherwise
Definition: MyGUI_UString.cpp:627
MyGUI
Definition: MyGUI_ActionController.h:15
MyGUI::TextCommandInfo
Definition: MyGUI_TextChangeHistory.h:20
MyGUI::UString::end
iterator end()
returns an iterator just past the end of the string
Definition: MyGUI_UString.cpp:803
MyGUI::TextIterator::eraseFromStart
bool eraseFromStart()
Definition: MyGUI_TextIterator.cpp:299
MyGUI::FontCodeType::NEL
@ NEL
Definition: MyGUI_FontData.h:24
MyGUI::UString::substr
UString substr(size_type index, size_type num=npos) const
returns a substring of the current string, starting at index, and num characters long.
Definition: MyGUI_UString.cpp:652
MyGUI::TextIterator::toTagsString
static UString toTagsString(const UString &_text)
Definition: MyGUI_TextIterator.cpp:358
MyGUI::UString::insert
iterator insert(iterator i, const code_point &ch)
inserts ch before the code point denoted by i
Definition: MyGUI_UString.cpp:1051
MyGUI_TextIterator.h
MyGUI::FontCodeType::LF
@ LF
Definition: MyGUI_FontData.h:21
MyGUI::TextIterator::setText
void setText(const UString &_text, bool _multiLine)
Definition: MyGUI_TextIterator.cpp:320
MyGUI::TextIterator::convertTagColour
static UString convertTagColour(const Colour &_colour)
Definition: MyGUI_TextIterator.cpp:345