MyGUI 3.4.1
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
140 UString tmpStr = UString(buff);
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();
277 if (character == FontCodeType::NEL ||
278 character == FontCodeType::CR ||
279 character == FontCodeType::LF )
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
308 void TextIterator::insertText(const UString& _insert, bool _multiLine)
309 {
310 UString text = _insert;
311
312 normaliseNewLine(text);
313
314 if (!_multiLine)
315 clearNewLine(text);
316
317 insert(mCurrent, text.asUTF32());
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.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)
UString getFromStart() const
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
_fwd_iterator & moveNext()
advances to the next Unicode character, honoring surrogate pairs in the UTF-16 stream
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
size_type size() const
Returns the number of code points in the current string.
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 erase(iterator loc)
removes the code point pointed to by loc, returning an iterator to the next character
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
Definition: MyGUI_Macros.h:17
unsigned int Char
Definition: MyGUI_Types.h:49
std::vector< TextCommandInfo > VectorChangeInfo