MyGUI 3.4.3
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"
9
10namespace 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.asUTF32()),
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)
36 return false;
37 if (mFirst)
38 {
39 mFirst = false;
40 return true;
41 }
42
43 // jump to next character, skipping tags (#)
44 for (UString::utf32string::iterator iter = mCurrent; iter != mEnd; ++iter)
45 {
46 if ((*iter) == L'#')
47 {
48 // следующий символ
49 ++iter;
50 if (iter == mEnd)
51 {
52 mCurrent = mEnd;
53 return false;
54 }
55
56 // две решетки подряд
57 if ((*iter) == L'#')
58 {
59 // следующий символ
60 mPosition++;
61 ++iter;
62 if (iter == mEnd)
63 {
64 mCurrent = mEnd;
65 return false;
66 }
67
68 // указатель на следующий символ
69 mCurrent = iter;
70 return true;
71 }
72
73 // остальные 5 символов цвета
74 for (size_t pos = 0; pos < 5; pos++)
75 {
76 // следующий символ
77 ++iter;
78 if (iter == mEnd)
79 {
80 mCurrent = mEnd;
81 return false;
82 }
83 }
84 }
85 else
86 {
87 // обыкновенный символ
88 mPosition++;
89 ++iter;
90 if (iter == mEnd)
91 {
92 mCurrent = mEnd;
93 return false;
94 }
95
96 // указатель на следующий символ
97 mCurrent = iter;
98 return true;
99 }
100 }
101
102 return false;
103 }
104
105 // возвращает цвет
107 {
108 if (mCurrent == mEnd)
109 return false;
110
111 UString::utf32string::iterator iter = mCurrent;
112
113 // нам нужен последний цвет
114 bool ret = false;
115 while (getTagColour(_colour, iter))
116 {
117 ret = true;
118 }
119
120 return ret;
121 }
122
124 {
125 if (mCurrent == mEnd)
126 return false;
128 if (mCurrent == mEnd)
129 return false;
130
131 const size_t SIZE = 16;
132 wchar_t buff[SIZE];
133
134#ifdef __MINGW32__
135 swprintf(
136 buff,
137 L"#%.2X%.2X%.2X\0",
138 (int)(_colour.red * 255),
139 (int)(_colour.green * 255),
140 (int)(_colour.blue * 255));
141#else
142 swprintf(
143 buff,
144 SIZE,
145 L"#%.2X%.2X%.2X\0",
146 (int)(_colour.red * 255),
147 (int)(_colour.green * 255),
148 (int)(_colour.blue * 255));
149#endif
151 insert(mCurrent, tmpStr.asUTF32());
152
153 return true;
154 }
155
157 {
158 if (mCurrent == mEnd)
159 return false;
161 if (mCurrent == mEnd)
162 return false;
163
164 // check if it looks like a colour tag
165 if ((_colour.size() != 7) || (_colour.find(L'#', 1) != MyGUI::UString::npos))
166 return false;
167
168 insert(mCurrent, _colour);
169
170 return true;
171 }
172
174 {
175 return setTagColour(_colour.asUTF32());
176 }
177
178 // возвращает размер строки
180 {
181 if (mSize != ITEM_NONE)
182 return mSize;
183 mSize = mPosition;
184
185 for (UString::utf32string::const_iterator iter = mCurrent; iter != mEnd; ++iter)
186 {
187 if ((*iter) == L'#')
188 {
189 // следующий символ
190 ++iter;
191 if (iter == mEnd)
192 break;
193
194 // тэг цвета
195 if ((*iter) != L'#')
196 {
197 // остальные 5 символов цвета
198 for (size_t pos = 0; pos < 5; pos++)
199 {
200 ++iter;
201 if (iter == mEnd)
202 {
203 --iter;
204 break;
205 }
206 }
207 continue;
208 }
209 }
210
211 // обыкновенный символ
212 mSize++;
213 }
214
215 return mSize;
216 }
217
218 // возвращает текст без тегов
220 {
222 UString::utf32string text(_text.asUTF32());
223 ret.reserve(text.size());
224
225 UString::utf32string::const_iterator end = text.end();
226 for (UString::utf32string::const_iterator iter = text.begin(); iter != end; ++iter)
227 {
228 if ((*iter) == L'#')
229 {
230 // следующий символ
231 ++iter;
232 if (iter == end)
233 break;
234
235 // тэг цвета
236 if ((*iter) != L'#')
237 {
238 // остальные 5 символов цвета
239 for (size_t pos = 0; pos < 5; pos++)
240 {
241 ++iter;
242 if (iter == end)
243 {
244 --iter;
245 break;
246 }
247 }
248 continue;
249 }
250 }
251
252 // обыкновенный символ
253 ret.push_back(*iter);
254 }
255
256 return UString(ret);
257 }
258
259 // возвращает цвет
260 bool TextIterator::getTagColour(UString& _colour, UString::utf32string::iterator& _iter) const
261 {
262 if ((_iter == mEnd) || ((*_iter) != L'#'))
263 return false;
264
265 // следующий символ
266 ++_iter;
267 if ((_iter == mEnd) || ((*_iter) == L'#'))
268 return false;
269
270 // берем цвет
271 wchar_t buff[16] = L"#FFFFFF\0";
272 buff[1] = (wchar_t)(*_iter);
273 for (size_t pos = 2; pos < 7; pos++)
274 {
275 ++_iter;
276 if (_iter == mEnd)
277 return false;
278 buff[pos] = (wchar_t)(*_iter);
279 }
280
281 // ставим на следующий тег или символ
282 ++_iter;
283
284 // возвращаем цвет
285 _colour = buff;
286 return true;
287 }
288
290 {
291 for (UString::iterator iter = _text.begin(); iter != _text.end(); iter.moveNext())
292 {
293 auto character = iter.getCharacter();
295 {
296 (*iter) = FontCodeType::Space;
297 }
298 }
299 }
300
302 {
303 if (mCurrent == mEnd)
304 return false;
305 mSave = mCurrent;
306 return true;
307 }
308
310 {
311 if (mSave == mEnd)
312 return {};
313 size_t start = mSave - mText.begin();
314 return UString(mText.substr(start, mCurrent - mText.begin() - start));
315 }
316
318 {
319 if (mSave == mEnd)
320 return false;
321 mCurrent = erase(mSave, mCurrent);
322 mSave = mEnd = mText.end();
323 return true;
324 }
325
327 {
328 UString text = _insert;
329
330 normaliseNewLine(text);
331
332 if (!_multiLine)
333 clearNewLine(text);
334
335 insert(mCurrent, text.asUTF32());
336 }
337
339 {
340 // сначала все очищаем
341 clear();
342
343 // а теперь вставляем
344 UString text = _text;
345
346 // нормализуем
347 normaliseNewLine(text);
348
349 if (!_multiLine)
350 clearNewLine(text);
351
352 insert(mCurrent, text.asUTF32());
353 }
354
356 {
357 if (_char == L'#')
358 return L"##";
359 wchar_t buff[16] = L"_\0";
360 buff[0] = (wchar_t)_char;
361 return buff;
362 }
363
365 {
366 const size_t SIZE = 16;
367 wchar_t buff[SIZE];
368//FIXME
369#ifdef __MINGW32__
370 swprintf(
371 buff,
372 L"#%.2X%.2X%.2X\0",
373 (int)(_colour.red * 255),
374 (int)(_colour.green * 255),
375 (int)(_colour.blue * 255));
376#else
377 swprintf(
378 buff,
379 SIZE,
380 L"#%.2X%.2X%.2X\0",
381 (int)(_colour.red * 255),
382 (int)(_colour.green * 255),
383 (int)(_colour.blue * 255));
384#endif
385 return buff;
386 }
387
389 {
390 // преобразуем в строку с тегами
391 UString text(_text);
392 for (UString::iterator iter = text.begin(); iter != text.end(); iter.moveNext())
393 {
394 // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
395 if (L'#' == (*iter))
396 iter = text.insert(iter.moveNext(), L'#');
397 }
398 return text;
399 }
400
401 void TextIterator::insert(UString::utf32string::iterator& _start, const UString::utf32string& _insert)
402 {
403 // сбрасываем размер
404 mSize = ITEM_NONE;
405 // записываем в историю
406 if (mHistory)
407 mHistory->push_back(TextCommandInfo(_insert, _start - mText.begin(), TextCommandInfo::COMMAND_INSERT));
408 // запоминаем позицию итератора
409 size_t pos = _start - mText.begin();
410 size_t pos_save = (mSave == mEnd) ? ITEM_NONE : _start - mText.begin();
411 // непосредственно вставляем
412 mText.insert(_start, _insert.begin(), _insert.end());
413 // возвращаем итераторы
414 _start = mText.begin() + pos;
415 mEnd = mText.end();
416 (pos_save == ITEM_NONE) ? mSave = mEnd : mSave = mText.begin() + pos_save;
417 }
418
419 UString::utf32string::iterator TextIterator::erase(
420 UString::utf32string::iterator _start,
421 UString::utf32string::iterator _end)
422 {
423 // сбрасываем размер
424 mSize = ITEM_NONE;
425 // сохраняем в историю
426 size_t start = _start - mText.begin();
427 if (mHistory)
428 mHistory->push_back(
429 TextCommandInfo(mText.substr(start, _end - _start), start, TextCommandInfo::COMMAND_ERASE));
430 // возвращаем итератор
431 return mText.erase(_start, _end);
432 }
433
434 void TextIterator::clear()
435 {
436 if (mText.empty())
437 return;
438
439 // записываем в историю
440 if (mHistory)
441 mHistory->push_back(TextCommandInfo(mText, 0, TextCommandInfo::COMMAND_ERASE));
442
443 // все сбрасываем
444 mText.clear();
445 mCurrent = mText.begin();
446 mEnd = mSave = mText.end();
447 mSize = ITEM_NONE;
448 }
449
451 {
452 if ((mSize != ITEM_NONE) && (mSize <= _max))
453 return;
454 if (mPosition > _max)
455 {
456 // придется считать сначала
457 mSize = mPosition = 0;
458 mCurrent = mText.begin();
459 mEnd = mSave = mText.end();
460 }
461
462 mSize = mPosition;
463
464 for (UString::utf32string::iterator iter = mCurrent; iter != mEnd; ++iter)
465 {
466 if ((*iter) == L'#')
467 {
468 // следующий символ
469 ++iter;
470 if (iter == mEnd)
471 break;
472
473 // тэг цвета
474 if ((*iter) != L'#')
475 {
476 // остальные 5 символов цвета
477 for (size_t pos = 0; pos < 5; pos++)
478 {
479 ++iter;
480 if (iter == mEnd)
481 {
482 --iter;
483 break;
484 }
485 }
486 continue;
487 }
488 }
489
490 // проверяем и обрезаем
491 if (mSize == _max)
492 {
493 mPosition = mSize; // сохраняем
494 mCurrent = erase(iter, mEnd);
495 mSave = mEnd = mText.end();
496 mSize = mPosition; // восстанавливаем
497 return;
498 }
499
500 // увеличиваем
501 mSize++;
502 }
503 }
504
506 {
507 // узнаем размер без тегов
508 size_t size = getSize();
509 if (size <= _max)
510 return;
511
512 // разница
513 size_t diff = size - _max;
514
515 // последний цвет
516 UString::utf32string::iterator iter_colour = mEnd;
517
518 // теперь пройдем от начала и узнаем реальную позицию разницы
519 UString::utf32string::iterator iter = mText.begin();
520 for (; iter != mEnd; ++iter)
521 {
522 if ((*iter) == L'#')
523 {
524 UString::utf32string::iterator save = iter;
525
526 // следующий символ
527 ++iter;
528 if (iter == mEnd)
529 break;
530
531 // тэг цвета
532 if ((*iter) != L'#')
533 {
534 // остальные 5 символов цвета
535 for (size_t pos = 0; pos < 5; pos++)
536 {
537 ++iter;
538 if (iter == mEnd)
539 {
540 --iter;
541 break;
542 }
543 }
544 // сохраняем цвет
545 iter_colour = save;
546 }
547 continue;
548 }
549 // обычный символ был
550 if (diff == 0)
551 break;
552 --diff;
553 }
554
556 // если бы цвет, то вставляем назад
557 if (iter_colour != mEnd)
558 {
559 colour.append(iter_colour, iter_colour + size_t(7));
560 }
561
562 mCurrent = erase(mText.begin(), iter);
563 mEnd = mText.end();
564 mSave = mText.end(); //FIXME
565 mPosition = 0;
566 mSize = _max;
567
568 if (!colour.empty())
569 setTagColour(colour);
570 }
571
573 {
574 if (mCurrent == mEnd)
575 return;
576
577 UString::utf32string::iterator iter = mCurrent;
578 UString colour;
579 // нам нужен последний цвет
580 while (getTagColour(colour, iter))
581 {
582 // обязательно обновляем итераторы
583 iter = mCurrent = erase(mCurrent, iter);
584 mEnd = mText.end();
585 }
586 }
587
589 {
590 return mPosition;
591 }
592
594 {
595 return UString(mText);
596 }
597
599 {
600 clear();
601 }
602
604 {
605 return L"\n";
606 }
607
608 void TextIterator::normaliseNewLine(UString& _text)
609 {
610 for (size_t index = 0; index < _text.size(); ++index)
611 {
612 Char character = _text[index];
613 if ((character == FontCodeType::CR) && ((index + 1) < _text.size()) &&
614 (_text[index + 1] == FontCodeType::LF))
615 {
616 _text.erase(index, 1);
617 }
618 }
619 }
620
621} // namespace MyGUI
static UString getOnlyText(const UString &_text)
void clearNewLine(UString &_text)
static UString getTextNewLine()
static UString getTextCharInfo(Char _char)
void cutMaxLength(size_t _max)
bool setTagColour(const Colour &_colour)
static UString convertTagColour(const Colour &_colour)
static UString toTagsString(const UString &_text)
void cutMaxLengthFromBeginning(size_t _max)
void setText(const UString &_text, bool _multiLine)
void insertText(const UString &_insert, bool _multiLine)
bool getTagColour(UString &_colour) const
forward iterator for UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
iterator insert(iterator i, const code_point &ch)
inserts ch before the code point denoted by i
const utf32string & asUTF32() const
returns the current string in UTF-32 form within a utf32string
std::basic_string< unicode_char > utf32string
string type used for returning UTF-32 formatted data
iterator end()
returns an iterator just past the end of the string
static const size_type npos
the usual constant representing: not found, no limit, etc
iterator begin()
returns an iterator to the first element of the string
constexpr size_t ITEM_NONE
unsigned int Char
Definition MyGUI_Types.h:50
std::vector< TextCommandInfo > VectorChangeInfo