MyGUI  3.2.0
MyGUI_TextIterator.cpp
Go to the documentation of this file.
1 
6 /*
7  This file is part of MyGUI.
8 
9  MyGUI is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  MyGUI is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include "MyGUI_Precompiled.h"
23 #include "MyGUI_TextIterator.h"
24 
25 namespace MyGUI
26 {
27 
28  TextIterator::TextIterator() :
29  mPosition(0),
30  mSize(ITEM_NONE),
31  mFirst(true),
32  mHistory(nullptr)
33  {
34  }
35 
36  TextIterator::TextIterator(const UString& _text, VectorChangeInfo* _history) :
37  mText(_text),
38  mCurrent(mText.begin()),
39  mEnd(mText.end()),
40  mSave(mEnd),
41  mPosition(0),
42  mSize(ITEM_NONE),
43  mFirst(true),
44  mHistory(_history)
45  {
46  }
47 
49  {
50  if (mCurrent == mEnd) return false;
51  else if (mFirst)
52  {
53  mFirst = false;
54  return true;
55  }
56 
57  // ставим на следующий символ проскакивая все тэги
58  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
59  {
60 
61  if ((*iter) == L'#')
62  {
63 
64  // следующий символ
65  ++ iter;
66  if (iter == mEnd)
67  {
68  mCurrent = mEnd;
69  return false;
70  }
71 
72  // две решетки подряд
73  if ((*iter) == L'#')
74  {
75 
76  // следующий символ
77  mPosition ++;
78  ++iter;
79  if (iter == mEnd)
80  {
81  mCurrent = mEnd;
82  return false;
83  }
84 
85  // указатель на следующий символ
86  mCurrent = iter;
87  return true;
88  }
89 
90  // остальные 5 символов цвета
91  for (size_t pos = 0; pos < 5; pos++)
92  {
93  // следующий символ
94  ++ iter;
95  if (iter == mEnd)
96  {
97  mCurrent = mEnd;
98  return false;
99  }
100  }
101 
102  }
103  else
104  {
105 
106  // обыкновенный символ
107  mPosition ++;
108  ++iter;
109  if (iter == mEnd)
110  {
111  mCurrent = mEnd;
112  return false;
113  }
114 
115  // указатель на следующий символ
116  mCurrent = iter;
117  return true;
118  }
119  }
120 
121  return false;
122  }
123 
124  // возвращает цвет
125  bool TextIterator::getTagColour(UString& _colour) const
126  {
127  if (mCurrent == mEnd) return false;
128 
129  UString::iterator iter = mCurrent;
130 
131  // нам нужен последний цвет
132  bool ret = false;
133  while (getTagColour(_colour, iter))
134  {
135  ret = true;
136  }
137 
138  return ret;
139  }
140 
141  bool TextIterator::setTagColour(const Colour& _colour)
142  {
143  if (mCurrent == mEnd) return false;
144  // очищаем все цвета
145  clearTagColour();
146  // на всякий
147  if (mCurrent == mEnd) return false;
148 
149  const size_t SIZE = 16;
150  wchar_t buff[SIZE];
151 
152 #ifdef __MINGW32__
153  swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
154 #else
155  swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
156 #endif
157  // непосредственная вставка
158  UString tmpStr = UString(buff);
159  insert(mCurrent, tmpStr);
160 
161  return true;
162  }
163 
165  {
166  if (mCurrent == mEnd) return false;
167  // очищаем все цвета
168  clearTagColour();
169  // на всякий
170  if (mCurrent == mEnd) return false;
171 
172  // проверяем на цвет хоть чуть чуть
173  if ( (_colour.size() != 7) || (_colour.find(L'#', 1) != _colour.npos) ) return false;
174 
175  // непосредственная вставка
176  insert(mCurrent, _colour);
177 
178  return true;
179  }
180 
181  // возвращает размер строки
182  size_t TextIterator::getSize() const
183  {
184  if (mSize != ITEM_NONE) return mSize;
185  mSize = mPosition;
186 
187  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
188  {
189 
190  if ((*iter) == L'#')
191  {
192  // следующий символ
193  ++ iter;
194  if (iter == mEnd) break;
195 
196  // тэг цвета
197  if ((*iter) != L'#')
198  {
199  // остальные 5 символов цвета
200  for (size_t pos = 0; pos < 5; pos++)
201  {
202  ++ iter;
203  if (iter == mEnd)
204  {
205  --iter;
206  break;
207  }
208  }
209  continue;
210  }
211  }
212 
213  // обыкновенный символ
214  mSize ++;
215  }
216 
217  return mSize;
218  }
219 
220  // возвращает текст без тегов
222  {
223  UString ret;
224  ret.reserve(_text.size());
225 
226  UString::const_iterator end = _text.end();
227  for (UString::const_iterator iter = _text.begin(); iter != end; ++iter)
228  {
229 
230  if ((*iter) == L'#')
231  {
232  // следующий символ
233  ++ iter;
234  if (iter == end) break;
235 
236  // тэг цвета
237  if ((*iter) != L'#')
238  {
239  // остальные 5 символов цвета
240  for (size_t pos = 0; pos < 5; pos++)
241  {
242  ++ iter;
243  if (iter == end)
244  {
245  --iter;
246  break;
247  }
248  }
249  continue;
250  }
251  }
252 
253  // обыкновенный символ
254  ret.push_back(*iter);
255  }
256 
257  return ret;
258  }
259 
260  // возвращает цвет
261  bool TextIterator::getTagColour(UString& _colour, UString::iterator& _iter) const
262  {
263  if ( (_iter == mEnd) || ((*_iter) != L'#') ) return false;
264 
265  // следующий символ
266  ++_iter;
267  if ( (_iter == mEnd) || ((*_iter) == L'#') ) return false;
268 
269  // берем цвет
270  wchar_t buff[16] = L"#FFFFFF\0";
271  buff[1] = (wchar_t)(*_iter);
272  for (size_t pos = 2; pos < 7; pos++)
273  {
274  ++_iter;
275  if ( _iter == mEnd ) return false;
276  buff[pos] = (wchar_t)(*_iter);
277  }
278 
279  // ставим на следующий тег или символ
280  ++_iter;
281 
282  // возвращаем цвет
283  _colour = buff;
284  return true;
285  }
286 
288  {
289  for (UString::iterator iter = _text.begin(); iter != _text.end(); ++iter)
290  {
291  if ( ((*iter) == FontCodeType::NEL) ||
292  ((*iter) == FontCodeType::CR) ||
293  ((*iter) == FontCodeType::LF) )
294  {
295  (*iter) = FontCodeType::Space;
296  }
297  }
298  }
299 
301  {
302  if (mCurrent == mEnd) return false;
303  mSave = mCurrent;
304  return true;
305  }
306 
308  {
309  if (mSave == mEnd) return L"";
310  size_t start = mSave - mText.begin();
311  return mText.substr(start, mCurrent - mText.begin() - start);
312  }
313 
315  {
316  if (mSave == mEnd) return false;
317  mCurrent = erase(mSave, mCurrent);
318  mSave = mEnd = mText.end();
319  return true;
320  }
321 
322  void TextIterator::insertText(const UString& _insert, bool _multiLine)
323  {
324  UString text = _insert;
325  if (!_multiLine) clearNewLine(text);
326  insert(mCurrent, text);
327  }
328 
329  void TextIterator::setText(const UString& _text, bool _multiLine)
330  {
331  // сначала все очищаем
332  clear();
333  // а теперь вставляем
334  UString text = _text;
335  if (!_multiLine) clearNewLine(text);
336  insert(mCurrent, text);
337  }
338 
340  {
341  if (_char == L'#') return L"##";
342  wchar_t buff[16] = L"_\0";
343  buff[0] = (wchar_t)_char;
344  return buff;
345  }
346 
348  {
349  const size_t SIZE = 16;
350  wchar_t buff[SIZE];
351 //FIXME
352 #ifdef __MINGW32__
353  swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
354 #else
355  swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
356 #endif
357  return buff;
358  }
359 
361  {
362  // преобразуем в строку с тегами
363  UString text(_text);
364  for (UString::iterator iter = text.begin(); iter != text.end(); ++iter)
365  {
366  // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
367  if (L'#' == (*iter)) iter = text.insert(++iter, L'#');
368  }
369  return text;
370  }
371 
372  void TextIterator::insert(UString::iterator& _start, UString& _insert)
373  {
374  // сбрасываем размер
375  mSize = ITEM_NONE;
376  // записываем в историю
377  if (mHistory) mHistory->push_back(TextCommandInfo(_insert, _start - mText.begin(), TextCommandInfo::COMMAND_INSERT));
378  // запоминаем позицию итератора
379  size_t pos = _start - mText.begin();
380  size_t pos_save = (mSave == mEnd) ? ITEM_NONE : _start - mText.begin();
381  // непосредственно вставляем
382  mText.insert(_start, _insert.begin(), _insert.end());
383  // возвращаем итераторы
384  _start = mText.begin() + pos;
385  mEnd = mText.end();
386  (pos_save == ITEM_NONE) ? mSave = mEnd : mSave = mText.begin() + pos_save;
387  }
388 
389  UString::iterator TextIterator::erase(UString::iterator _start, UString::iterator _end)
390  {
391  // сбрасываем размер
392  mSize = ITEM_NONE;
393  // сохраняем в историю
394  size_t start = _start - mText.begin();
395  if (mHistory) mHistory->push_back(TextCommandInfo(mText.substr(start, _end - _start), start, TextCommandInfo::COMMAND_ERASE));
396  // возвращаем итератор
397  return mText.erase(_start, _end);
398  }
399 
400  void TextIterator::clear()
401  {
402  if (mText.empty()) return;
403 
404  // записываем в историю
405  if (mHistory) mHistory->push_back(TextCommandInfo(mText, 0, TextCommandInfo::COMMAND_ERASE));
406 
407  // все сбрасываем
408  mText.clear();
409  mCurrent = mText.begin();
410  mEnd = mSave = mText.end();
411  mSize = ITEM_NONE;
412  }
413 
414  void TextIterator::cutMaxLength(size_t _max)
415  {
416  if ( (mSize != ITEM_NONE) && (mSize <= _max) ) return;
417  if (mPosition > _max)
418  {
419  // придется считать сначала
420  mSize = mPosition = 0;
421  mCurrent = mText.begin();
422  mEnd = mSave = mText.end();
423  }
424 
425  mSize = mPosition;
426 
427  for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
428  {
429 
430  if ((*iter) == L'#')
431  {
432  // следующий символ
433  ++ iter;
434  if (iter == mEnd) break;
435 
436  // тэг цвета
437  if ((*iter) != L'#')
438  {
439  // остальные 5 символов цвета
440  for (size_t pos = 0; pos < 5; pos++)
441  {
442  ++ iter;
443  if (iter == mEnd)
444  {
445  -- iter;
446  break;
447  }
448  }
449  continue;
450  }
451  }
452 
453  // проверяем и обрезаем
454  if (mSize == _max)
455  {
456  mPosition = mSize; // сохраняем
457  mCurrent = erase(iter, mEnd);
458  mSave = mEnd = mText.end();
459  mSize = mPosition; // восстанавливаем
460  return;
461  }
462 
463  // увеличиваем
464  mSize ++;
465  }
466  }
467 
469  {
470  // узнаем размер без тегов
471  size_t size = getSize();
472  if (size <= _max) return;
473 
474  // разница
475  size_t diff = size - _max;
476 
477  // последний цвет
478  UString::iterator iter_colour = mEnd;
479 
480  // теперь пройдем от начала и узнаем реальную позицию разницы
481  UString::iterator iter = mText.begin();
482  for (; iter != mEnd; ++iter)
483  {
484  if ((*iter) == L'#')
485  {
486  UString::iterator save = iter;
487 
488  // следующий символ
489  ++ iter;
490  if (iter == mEnd) break;
491 
492  // тэг цвета
493  if ((*iter) != L'#')
494  {
495  // остальные 5 символов цвета
496  for (size_t pos = 0; pos < 5; pos++)
497  {
498  ++ iter;
499  if (iter == mEnd)
500  {
501  -- iter;
502  break;
503  }
504  }
505  // сохраняем цвет
506  iter_colour = save;
507  }
508  continue;
509  }
510  // обычный символ был
511  if (diff == 0) break;
512  -- diff;
513  }
514 
515  UString colour;
516  // если бы цвет, то вставляем назад
517  if (iter_colour != mEnd)
518  {
519  colour.append(iter_colour, iter_colour + size_t(7));
520  }
521 
522  mCurrent = erase(mText.begin(), iter);
523  mEnd = mText.end();
524  mSave = mText.end(); //FIXME
525  mPosition = 0;
526  mSize = _max;
527 
528  if ( ! colour.empty() ) setTagColour(colour);
529 
530  }
531 
533  {
534  if (mCurrent == mEnd) return;
535 
536  UString::iterator iter = mCurrent;
537  UString colour;
538  // нам нужен последний цвет
539  while (getTagColour(colour, iter))
540  {
541  // обязательно обновляем итераторы
542  iter = mCurrent = erase(mCurrent, iter);
543  mEnd = mText.end();
544  }
545  }
546 
548  {
549  return mPosition;
550  }
551 
553  {
554  return mText;
555  }
556 
558  {
559  clear();
560  }
561 
563  {
564  return L"\n";
565  }
566 
567 } // namespace MyGUI