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