MyGUI 3.4.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"
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) return false;
36 else if (mFirst)
37 {
38 mFirst = false;
39 return true;
40 }
41
42 // jump to next character, skipping tags (#)
43 for (UString::utf32string::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 // возвращает цвет
111 {
112 if (mCurrent == mEnd) return false;
113
114 UString::utf32string::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
127 {
128 if (mCurrent == mEnd) return false;
130 if (mCurrent == mEnd) return false;
131
132 const size_t SIZE = 16;
133 wchar_t buff[SIZE];
134
135#ifdef __MINGW32__
136 swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
137#else
138 swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
139#endif
141 insert(mCurrent, tmpStr.asUTF32());
142
143 return true;
144 }
145
147 {
148 if (mCurrent == mEnd) return false;
150 if (mCurrent == mEnd) return false;
151
152 // check if it looks like a colour tag
153 if ( (_colour.size() != 7) || (_colour.find(L'#', 1) != MyGUI::UString::npos) ) return false;
154
155 insert(mCurrent, _colour);
156
157 return true;
158 }
159
161 {
162 return setTagColour(_colour.asUTF32());
163 }
164
165 // возвращает размер строки
167 {
168 if (mSize != ITEM_NONE) return mSize;
169 mSize = mPosition;
170
171 for (UString::utf32string::const_iterator iter = mCurrent; iter != mEnd; ++iter)
172 {
173
174 if ((*iter) == L'#')
175 {
176 // следующий символ
177 ++ iter;
178 if (iter == mEnd) break;
179
180 // тэг цвета
181 if ((*iter) != L'#')
182 {
183 // остальные 5 символов цвета
184 for (size_t pos = 0; pos < 5; pos++)
185 {
186 ++ iter;
187 if (iter == mEnd)
188 {
189 --iter;
190 break;
191 }
192 }
193 continue;
194 }
195 }
196
197 // обыкновенный символ
198 mSize ++;
199 }
200
201 return mSize;
202 }
203
204 // возвращает текст без тегов
206 {
208 UString::utf32string text(_text.asUTF32());
209 ret.reserve(text.size());
210
211 UString::utf32string::const_iterator end = text.end();
212 for (UString::utf32string::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 UString(ret);
243 }
244
245 // возвращает цвет
246 bool TextIterator::getTagColour(UString& _colour, UString::utf32string::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.moveNext())
275 {
276 auto character = iter.getCharacter();
280 {
281 (*iter) = FontCodeType::Space;
282 }
283 }
284 }
285
287 {
288 if (mCurrent == mEnd) return false;
289 mSave = mCurrent;
290 return true;
291 }
292
294 {
295 if (mSave == mEnd) return L"";
296 size_t start = mSave - mText.begin();
297 return UString(mText.substr(start, mCurrent - mText.begin() - start));
298 }
299
301 {
302 if (mSave == mEnd) return false;
303 mCurrent = erase(mSave, mCurrent);
304 mSave = mEnd = mText.end();
305 return true;
306 }
307
309 {
310 UString text = _insert;
311
312 normaliseNewLine(text);
313
314 if (!_multiLine)
315 clearNewLine(text);
316
317 insert(mCurrent, text.asUTF32());
318 }
319
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.asUTF32());
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.moveNext())
363 {
364 // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
365 if (L'#' == (*iter)) iter = text.insert(iter.moveNext(), L'#');
366 }
367 return text;
368 }
369
370 void TextIterator::insert(UString::utf32string::iterator& _start, const UString::utf32string& _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::utf32string::iterator TextIterator::erase(UString::utf32string::iterator _start, UString::utf32string::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
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::utf32string::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::utf32string::iterator iter_colour = mEnd;
477
478 // теперь пройдем от начала и узнаем реальную позицию разницы
479 UString::utf32string::iterator iter = mText.begin();
480 for (; iter != mEnd; ++iter)
481 {
482 if ((*iter) == L'#')
483 {
484 UString::utf32string::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
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::utf32string::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 UString(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 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
const size_t ITEM_NONE
unsigned int Char
Definition MyGUI_Types.h:50
std::vector< TextCommandInfo > VectorChangeInfo