MyGUI 3.2.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"
8 #include "MyGUI_TextIterator.h"
9
10 namespace 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),
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
33 bool TextIterator::moveNext()
34 {
35 if (mCurrent == mEnd) return false;
36 else if (mFirst)
37 {
38 mFirst = false;
39 return true;
40 }
41
42 // ставим на следующий символ проскакивая все тэги
43 for (UString::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 // возвращает цвет
110 bool TextIterator::getTagColour(UString& _colour) const
111 {
112 if (mCurrent == mEnd) return false;
113
114 UString::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
126 bool TextIterator::setTagColour(const Colour& _colour)
127 {
128 if (mCurrent == mEnd) return false;
129 // очищаем все цвета
130 clearTagColour();
131 // на всякий
132 if (mCurrent == mEnd) return false;
133
134 const size_t SIZE = 16;
135 wchar_t buff[SIZE];
136
137 #ifdef __MINGW32__
138 swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
139 #else
140 swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255));
141 #endif
142 // непосредственная вставка
143 UString tmpStr = UString(buff);
144 insert(mCurrent, tmpStr);
145
146 return true;
147 }
148
149 bool TextIterator::setTagColour(UString _colour)
150 {
151 if (mCurrent == mEnd) return false;
152 // очищаем все цвета
153 clearTagColour();
154 // на всякий
155 if (mCurrent == mEnd) return false;
156
157 // проверяем на цвет хоть чуть чуть
158 if ( (_colour.size() != 7) || (_colour.find(L'#', 1) != _colour.npos) ) return false;
159
160 // непосредственная вставка
161 insert(mCurrent, _colour);
162
163 return true;
164 }
165
166 // возвращает размер строки
167 size_t TextIterator::getSize() const
168 {
169 if (mSize != ITEM_NONE) return mSize;
170 mSize = mPosition;
171
172 for (UString::iterator iter = mCurrent; iter != mEnd; ++iter)
173 {
174
175 if ((*iter) == L'#')
176 {
177 // следующий символ
178 ++ iter;
179 if (iter == mEnd) break;
180
181 // тэг цвета
182 if ((*iter) != L'#')
183 {
184 // остальные 5 символов цвета
185 for (size_t pos = 0; pos < 5; pos++)
186 {
187 ++ iter;
188 if (iter == mEnd)
189 {
190 --iter;
191 break;
192 }
193 }
194 continue;
195 }
196 }
197
198 // обыкновенный символ
199 mSize ++;
200 }
201
202 return mSize;
203 }
204
205 // возвращает текст без тегов
206 UString TextIterator::getOnlyText(const UString& _text)
207 {
208 UString ret;
209 ret.reserve(_text.size());
210
211 UString::const_iterator end = _text.end();
212 for (UString::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 ret;
243 }
244
245 // возвращает цвет
246 bool TextIterator::getTagColour(UString& _colour, UString::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
272 void TextIterator::clearNewLine(UString& _text)
273 {
274 for (UString::iterator iter = _text.begin(); iter != _text.end(); ++iter)
275 {
276 if ( ((*iter) == FontCodeType::NEL) ||
277 ((*iter) == FontCodeType::CR) ||
278 ((*iter) == FontCodeType::LF) )
279 {
280 (*iter) = FontCodeType::Space;
281 }
282 }
283 }
284
285 bool TextIterator::saveStartPoint()
286 {
287 if (mCurrent == mEnd) return false;
288 mSave = mCurrent;
289 return true;
290 }
291
292 UString TextIterator::getFromStart()
293 {
294 if (mSave == mEnd) return L"";
295 size_t start = mSave - mText.begin();
296 return mText.substr(start, mCurrent - mText.begin() - start);
297 }
298
299 bool TextIterator::eraseFromStart()
300 {
301 if (mSave == mEnd) return false;
302 mCurrent = erase(mSave, mCurrent);
303 mSave = mEnd = mText.end();
304 return true;
305 }
306
307 void TextIterator::insertText(const UString& _insert, bool _multiLine)
308 {
309 UString text = _insert;
310
311 // нормализуем
312 normaliseNewLine(text);
313
314 if (!_multiLine)
315 clearNewLine(text);
316
317 insert(mCurrent, text);
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);
335 }
336
337 UString TextIterator::getTextCharInfo(Char _char)
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
345 UString TextIterator::convertTagColour(const Colour& _colour)
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
358 UString TextIterator::toTagsString(const UString& _text)
359 {
360 // преобразуем в строку с тегами
361 UString text(_text);
362 for (UString::iterator iter = text.begin(); iter != text.end(); ++iter)
363 {
364 // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
365 if (L'#' == (*iter)) iter = text.insert(++iter, L'#');
366 }
367 return text;
368 }
369
370 void TextIterator::insert(UString::iterator& _start, UString& _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::iterator TextIterator::erase(UString::iterator _start, UString::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
412 void TextIterator::cutMaxLength(size_t _max)
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::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
466 void TextIterator::cutMaxLengthFromBeginning(size_t _max)
467 {
468 // узнаем размер без тегов
469 size_t size = getSize();
470 if (size <= _max) return;
471
472 // разница
473 size_t diff = size - _max;
474
475 // последний цвет
476 UString::iterator iter_colour = mEnd;
477
478 // теперь пройдем от начала и узнаем реальную позицию разницы
479 UString::iterator iter = mText.begin();
480 for (; iter != mEnd; ++iter)
481 {
482 if ((*iter) == L'#')
483 {
484 UString::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
513 UString colour;
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
530 void TextIterator::clearTagColour()
531 {
532 if (mCurrent == mEnd) return;
533
534 UString::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
545 size_t TextIterator::getPosition() const
546 {
547 return mPosition;
548 }
549
550 const UString& TextIterator::getText() const
551 {
552 return mText;
553 }
554
555 void TextIterator::clearText()
556 {
557 clear();
558 }
559
560 UString TextIterator::getTextNewLine()
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
MyGUI::TextIterator::getTextCharInfo
static UString getTextCharInfo(Char _char)
Definition: MyGUI_TextIterator.cpp:337
MyGUI::UString::empty
bool empty() const
returns true if the string has no elements, false otherwise
Definition: MyGUI_UString.cpp:627
MyGUI::TextIterator::clearNewLine
void clearNewLine(UString &_text)
Definition: MyGUI_TextIterator.cpp:272
MyGUI::UString::append
UString & append(const UString &str)
appends str on to the end of the current string
Definition: MyGUI_UString.cpp:974
MyGUI::TextIterator::cutMaxLength
void cutMaxLength(size_t _max)
Definition: MyGUI_TextIterator.cpp:412
MyGUI::VectorChangeInfo
std::vector< TextCommandInfo > VectorChangeInfo
Definition: MyGUI_TextChangeHistory.h:60
MyGUI::Colour::green
float green
Definition: MyGUI_Colour.h:50
MyGUI_Precompiled.h
MyGUI::TextIterator::getOnlyText
static UString getOnlyText(const UString &_text)
Definition: MyGUI_TextIterator.cpp:206
MyGUI::UString::erase
iterator erase(iterator loc)
removes the code point pointed to by loc, returning an iterator to the next character ...
Definition: MyGUI_UString.cpp:1164
MyGUI::TextIterator::getText
const UString & getText() const
Definition: MyGUI_TextIterator.cpp:550
MyGUI::ITEM_NONE
const size_t ITEM_NONE
Definition: MyGUI_Macros.h:17
MyGUI::UString::npos
static const size_type npos
the usual constant representing: not found, no limit, etc
Definition: MyGUI_UString.h:187
MyGUI::UString::_const_fwd_iterator
const forward iterator for UString
Definition: MyGUI_UString.h:289
MyGUI::FontCodeType::CR
Definition: MyGUI_FontData.h:22
nullptr
#define nullptr
Definition: MyGUI_Prerequest.h:29
MyGUI::UString::push_back
void push_back(unicode_char val)
appends val to the end of the string
Definition: MyGUI_UString.cpp:661
MyGUI::TextIterator::moveNext
bool moveNext()
Definition: MyGUI_TextIterator.cpp:33
MyGUI::UString::clear
void clear()
deletes all of the elements in the string
Definition: MyGUI_UString.cpp:647
MyGUI::TextIterator::getFromStart
UString getFromStart()
Definition: MyGUI_TextIterator.cpp:292
MyGUI::UString::begin
iterator begin()
returns an iterator to the first element of the string
Definition: MyGUI_UString.cpp:787
MyGUI::TextIterator::insertText
void insertText(const UString &_insert, bool _multiLine)
Definition: MyGUI_TextIterator.cpp:307
MyGUI::TextIterator::eraseFromStart
bool eraseFromStart()
Definition: MyGUI_TextIterator.cpp:299
MyGUI::TextCommandInfo
Definition: MyGUI_TextChangeHistory.h:19
MyGUI
Definition: MyGUI_ActionController.h:14
MyGUI::TextIterator::saveStartPoint
bool saveStartPoint()
Definition: MyGUI_TextIterator.cpp:285
MyGUI::TextIterator::toTagsString
static UString toTagsString(const UString &_text)
Definition: MyGUI_TextIterator.cpp:358
MyGUI::TextIterator::getSize
size_t getSize() const
Definition: MyGUI_TextIterator.cpp:167
MyGUI::FontCodeType::Space
Definition: MyGUI_FontData.h:23
MyGUI::TextIterator::getPosition
size_t getPosition() const
Definition: MyGUI_TextIterator.cpp:545
MyGUI::UString::find
size_type find(const UString &str, size_type index=0) const
returns the index of the first occurrence of str within the current string, starting at index; return...
Definition: MyGUI_UString.cpp:1270
MyGUI::Char
unsigned int Char
Definition: MyGUI_Types.h:51
MyGUI::UString::reserve
void reserve(size_type size)
sets the capacity of the string to at least size code points
Definition: MyGUI_UString.cpp:612
MyGUI::UString::_fwd_iterator
forward iterator for UString
Definition: MyGUI_UString.h:243
MyGUI::TextIterator::setText
void setText(const UString &_text, bool _multiLine)
Definition: MyGUI_TextIterator.cpp:320
MyGUI::TextIterator::setTagColour
bool setTagColour(const Colour &_colour)
Definition: MyGUI_TextIterator.cpp:126
MyGUI::Colour::red
float red
Definition: MyGUI_Colour.h:49
MyGUI::UString::size
size_type size() const
Returns the number of code points in the current string.
Definition: MyGUI_UString.cpp:586
MyGUI::TextCommandInfo::COMMAND_ERASE
Definition: MyGUI_TextChangeHistory.h:26
MyGUI::TextIterator::getTextNewLine
static UString getTextNewLine()
Definition: MyGUI_TextIterator.cpp:560
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition: MyGUI_UString.h:168
MyGUI::TextIterator::cutMaxLengthFromBeginning
void cutMaxLengthFromBeginning(size_t _max)
Definition: MyGUI_TextIterator.cpp:466
MyGUI::UString::insert
iterator insert(iterator i, const code_point &ch)
inserts ch before the code point denoted by i
Definition: MyGUI_UString.cpp:1051
MyGUI::Colour
Definition: MyGUI_Colour.h:16
MyGUI::UString::end
iterator end()
returns an iterator just past the end of the string
Definition: MyGUI_UString.cpp:803
MyGUI::UString::substr
UString substr(size_type index, size_type num=npos) const
returns a substring of the current string, starting at index, and num characters long.
Definition: MyGUI_UString.cpp:652
MyGUI::TextIterator::clearText
void clearText()
Definition: MyGUI_TextIterator.cpp:555
MyGUI::TextIterator::getTagColour
bool getTagColour(UString &_colour) const
Definition: MyGUI_TextIterator.cpp:110
MyGUI::FontCodeType::NEL
Definition: MyGUI_FontData.h:24
MyGUI::Colour::blue
float blue
Definition: MyGUI_Colour.h:51
MyGUI::TextIterator::clearTagColour
void clearTagColour()
Definition: MyGUI_TextIterator.cpp:530
MyGUI::FontCodeType::LF
Definition: MyGUI_FontData.h:21
MyGUI::TextIterator::convertTagColour
static UString convertTagColour(const Colour &_colour)
Definition: MyGUI_TextIterator.cpp:345
MyGUI_TextIterator.h
MyGUI::TextCommandInfo::COMMAND_INSERT
Definition: MyGUI_TextChangeHistory.h:25