MyGUI
3.2.1
|
00001 /* 00002 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 00003 * Distributed under the MIT License 00004 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 00005 */ 00006 00007 #include "MyGUI_Precompiled.h" 00008 #include "MyGUI_TextIterator.h" 00009 00010 namespace MyGUI 00011 { 00012 00013 TextIterator::TextIterator() : 00014 mPosition(0), 00015 mSize(ITEM_NONE), 00016 mFirst(true), 00017 mHistory(nullptr) 00018 { 00019 } 00020 00021 TextIterator::TextIterator(const UString& _text, VectorChangeInfo* _history) : 00022 mText(_text), 00023 mCurrent(mText.begin()), 00024 mEnd(mText.end()), 00025 mSave(mEnd), 00026 mPosition(0), 00027 mSize(ITEM_NONE), 00028 mFirst(true), 00029 mHistory(_history) 00030 { 00031 } 00032 00033 bool TextIterator::moveNext() 00034 { 00035 if (mCurrent == mEnd) return false; 00036 else if (mFirst) 00037 { 00038 mFirst = false; 00039 return true; 00040 } 00041 00042 // ставим на следующий символ проскакивая все тэги 00043 for (UString::iterator iter = mCurrent; iter != mEnd; ++iter) 00044 { 00045 00046 if ((*iter) == L'#') 00047 { 00048 00049 // следующий символ 00050 ++ iter; 00051 if (iter == mEnd) 00052 { 00053 mCurrent = mEnd; 00054 return false; 00055 } 00056 00057 // две решетки подряд 00058 if ((*iter) == L'#') 00059 { 00060 00061 // следующий символ 00062 mPosition ++; 00063 ++iter; 00064 if (iter == mEnd) 00065 { 00066 mCurrent = mEnd; 00067 return false; 00068 } 00069 00070 // указатель на следующий символ 00071 mCurrent = iter; 00072 return true; 00073 } 00074 00075 // остальные 5 символов цвета 00076 for (size_t pos = 0; pos < 5; pos++) 00077 { 00078 // следующий символ 00079 ++ iter; 00080 if (iter == mEnd) 00081 { 00082 mCurrent = mEnd; 00083 return false; 00084 } 00085 } 00086 00087 } 00088 else 00089 { 00090 00091 // обыкновенный символ 00092 mPosition ++; 00093 ++iter; 00094 if (iter == mEnd) 00095 { 00096 mCurrent = mEnd; 00097 return false; 00098 } 00099 00100 // указатель на следующий символ 00101 mCurrent = iter; 00102 return true; 00103 } 00104 } 00105 00106 return false; 00107 } 00108 00109 // возвращает цвет 00110 bool TextIterator::getTagColour(UString& _colour) const 00111 { 00112 if (mCurrent == mEnd) return false; 00113 00114 UString::iterator iter = mCurrent; 00115 00116 // нам нужен последний цвет 00117 bool ret = false; 00118 while (getTagColour(_colour, iter)) 00119 { 00120 ret = true; 00121 } 00122 00123 return ret; 00124 } 00125 00126 bool TextIterator::setTagColour(const Colour& _colour) 00127 { 00128 if (mCurrent == mEnd) return false; 00129 // очищаем все цвета 00130 clearTagColour(); 00131 // на всякий 00132 if (mCurrent == mEnd) return false; 00133 00134 const size_t SIZE = 16; 00135 wchar_t buff[SIZE]; 00136 00137 #ifdef __MINGW32__ 00138 swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255)); 00139 #else 00140 swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255)); 00141 #endif 00142 // непосредственная вставка 00143 UString tmpStr = UString(buff); 00144 insert(mCurrent, tmpStr); 00145 00146 return true; 00147 } 00148 00149 bool TextIterator::setTagColour(UString _colour) 00150 { 00151 if (mCurrent == mEnd) return false; 00152 // очищаем все цвета 00153 clearTagColour(); 00154 // на всякий 00155 if (mCurrent == mEnd) return false; 00156 00157 // проверяем на цвет хоть чуть чуть 00158 if ( (_colour.size() != 7) || (_colour.find(L'#', 1) != _colour.npos) ) return false; 00159 00160 // непосредственная вставка 00161 insert(mCurrent, _colour); 00162 00163 return true; 00164 } 00165 00166 // возвращает размер строки 00167 size_t TextIterator::getSize() const 00168 { 00169 if (mSize != ITEM_NONE) return mSize; 00170 mSize = mPosition; 00171 00172 for (UString::iterator iter = mCurrent; iter != mEnd; ++iter) 00173 { 00174 00175 if ((*iter) == L'#') 00176 { 00177 // следующий символ 00178 ++ iter; 00179 if (iter == mEnd) break; 00180 00181 // тэг цвета 00182 if ((*iter) != L'#') 00183 { 00184 // остальные 5 символов цвета 00185 for (size_t pos = 0; pos < 5; pos++) 00186 { 00187 ++ iter; 00188 if (iter == mEnd) 00189 { 00190 --iter; 00191 break; 00192 } 00193 } 00194 continue; 00195 } 00196 } 00197 00198 // обыкновенный символ 00199 mSize ++; 00200 } 00201 00202 return mSize; 00203 } 00204 00205 // возвращает текст без тегов 00206 UString TextIterator::getOnlyText(const UString& _text) 00207 { 00208 UString ret; 00209 ret.reserve(_text.size()); 00210 00211 UString::const_iterator end = _text.end(); 00212 for (UString::const_iterator iter = _text.begin(); iter != end; ++iter) 00213 { 00214 00215 if ((*iter) == L'#') 00216 { 00217 // следующий символ 00218 ++ iter; 00219 if (iter == end) break; 00220 00221 // тэг цвета 00222 if ((*iter) != L'#') 00223 { 00224 // остальные 5 символов цвета 00225 for (size_t pos = 0; pos < 5; pos++) 00226 { 00227 ++ iter; 00228 if (iter == end) 00229 { 00230 --iter; 00231 break; 00232 } 00233 } 00234 continue; 00235 } 00236 } 00237 00238 // обыкновенный символ 00239 ret.push_back(*iter); 00240 } 00241 00242 return ret; 00243 } 00244 00245 // возвращает цвет 00246 bool TextIterator::getTagColour(UString& _colour, UString::iterator& _iter) const 00247 { 00248 if ( (_iter == mEnd) || ((*_iter) != L'#') ) return false; 00249 00250 // следующий символ 00251 ++_iter; 00252 if ( (_iter == mEnd) || ((*_iter) == L'#') ) return false; 00253 00254 // берем цвет 00255 wchar_t buff[16] = L"#FFFFFF\0"; 00256 buff[1] = (wchar_t)(*_iter); 00257 for (size_t pos = 2; pos < 7; pos++) 00258 { 00259 ++_iter; 00260 if ( _iter == mEnd ) return false; 00261 buff[pos] = (wchar_t)(*_iter); 00262 } 00263 00264 // ставим на следующий тег или символ 00265 ++_iter; 00266 00267 // возвращаем цвет 00268 _colour = buff; 00269 return true; 00270 } 00271 00272 void TextIterator::clearNewLine(UString& _text) 00273 { 00274 for (UString::iterator iter = _text.begin(); iter != _text.end(); ++iter) 00275 { 00276 if ( ((*iter) == FontCodeType::NEL) || 00277 ((*iter) == FontCodeType::CR) || 00278 ((*iter) == FontCodeType::LF) ) 00279 { 00280 (*iter) = FontCodeType::Space; 00281 } 00282 } 00283 } 00284 00285 bool TextIterator::saveStartPoint() 00286 { 00287 if (mCurrent == mEnd) return false; 00288 mSave = mCurrent; 00289 return true; 00290 } 00291 00292 UString TextIterator::getFromStart() 00293 { 00294 if (mSave == mEnd) return L""; 00295 size_t start = mSave - mText.begin(); 00296 return mText.substr(start, mCurrent - mText.begin() - start); 00297 } 00298 00299 bool TextIterator::eraseFromStart() 00300 { 00301 if (mSave == mEnd) return false; 00302 mCurrent = erase(mSave, mCurrent); 00303 mSave = mEnd = mText.end(); 00304 return true; 00305 } 00306 00307 void TextIterator::insertText(const UString& _insert, bool _multiLine) 00308 { 00309 UString text = _insert; 00310 00311 // нормализуем 00312 normaliseNewLine(text); 00313 00314 if (!_multiLine) 00315 clearNewLine(text); 00316 00317 insert(mCurrent, text); 00318 } 00319 00320 void TextIterator::setText(const UString& _text, bool _multiLine) 00321 { 00322 // сначала все очищаем 00323 clear(); 00324 00325 // а теперь вставляем 00326 UString text = _text; 00327 00328 // нормализуем 00329 normaliseNewLine(text); 00330 00331 if (!_multiLine) 00332 clearNewLine(text); 00333 00334 insert(mCurrent, text); 00335 } 00336 00337 UString TextIterator::getTextCharInfo(Char _char) 00338 { 00339 if (_char == L'#') return L"##"; 00340 wchar_t buff[16] = L"_\0"; 00341 buff[0] = (wchar_t)_char; 00342 return buff; 00343 } 00344 00345 UString TextIterator::convertTagColour(const Colour& _colour) 00346 { 00347 const size_t SIZE = 16; 00348 wchar_t buff[SIZE]; 00349 //FIXME 00350 #ifdef __MINGW32__ 00351 swprintf(buff, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255)); 00352 #else 00353 swprintf(buff, SIZE, L"#%.2X%.2X%.2X\0", (int)(_colour.red * 255), (int)(_colour.green * 255), (int)(_colour.blue * 255)); 00354 #endif 00355 return buff; 00356 } 00357 00358 UString TextIterator::toTagsString(const UString& _text) 00359 { 00360 // преобразуем в строку с тегами 00361 UString text(_text); 00362 for (UString::iterator iter = text.begin(); iter != text.end(); ++iter) 00363 { 00364 // потом переделать через TextIterator чтобы отвязать понятие тег от эдита 00365 if (L'#' == (*iter)) iter = text.insert(++iter, L'#'); 00366 } 00367 return text; 00368 } 00369 00370 void TextIterator::insert(UString::iterator& _start, UString& _insert) 00371 { 00372 // сбрасываем размер 00373 mSize = ITEM_NONE; 00374 // записываем в историю 00375 if (mHistory) mHistory->push_back(TextCommandInfo(_insert, _start - mText.begin(), TextCommandInfo::COMMAND_INSERT)); 00376 // запоминаем позицию итератора 00377 size_t pos = _start - mText.begin(); 00378 size_t pos_save = (mSave == mEnd) ? ITEM_NONE : _start - mText.begin(); 00379 // непосредственно вставляем 00380 mText.insert(_start, _insert.begin(), _insert.end()); 00381 // возвращаем итераторы 00382 _start = mText.begin() + pos; 00383 mEnd = mText.end(); 00384 (pos_save == ITEM_NONE) ? mSave = mEnd : mSave = mText.begin() + pos_save; 00385 } 00386 00387 UString::iterator TextIterator::erase(UString::iterator _start, UString::iterator _end) 00388 { 00389 // сбрасываем размер 00390 mSize = ITEM_NONE; 00391 // сохраняем в историю 00392 size_t start = _start - mText.begin(); 00393 if (mHistory) mHistory->push_back(TextCommandInfo(mText.substr(start, _end - _start), start, TextCommandInfo::COMMAND_ERASE)); 00394 // возвращаем итератор 00395 return mText.erase(_start, _end); 00396 } 00397 00398 void TextIterator::clear() 00399 { 00400 if (mText.empty()) return; 00401 00402 // записываем в историю 00403 if (mHistory) mHistory->push_back(TextCommandInfo(mText, 0, TextCommandInfo::COMMAND_ERASE)); 00404 00405 // все сбрасываем 00406 mText.clear(); 00407 mCurrent = mText.begin(); 00408 mEnd = mSave = mText.end(); 00409 mSize = ITEM_NONE; 00410 } 00411 00412 void TextIterator::cutMaxLength(size_t _max) 00413 { 00414 if ( (mSize != ITEM_NONE) && (mSize <= _max) ) return; 00415 if (mPosition > _max) 00416 { 00417 // придется считать сначала 00418 mSize = mPosition = 0; 00419 mCurrent = mText.begin(); 00420 mEnd = mSave = mText.end(); 00421 } 00422 00423 mSize = mPosition; 00424 00425 for (UString::iterator iter = mCurrent; iter != mEnd; ++iter) 00426 { 00427 00428 if ((*iter) == L'#') 00429 { 00430 // следующий символ 00431 ++ iter; 00432 if (iter == mEnd) break; 00433 00434 // тэг цвета 00435 if ((*iter) != L'#') 00436 { 00437 // остальные 5 символов цвета 00438 for (size_t pos = 0; pos < 5; pos++) 00439 { 00440 ++ iter; 00441 if (iter == mEnd) 00442 { 00443 -- iter; 00444 break; 00445 } 00446 } 00447 continue; 00448 } 00449 } 00450 00451 // проверяем и обрезаем 00452 if (mSize == _max) 00453 { 00454 mPosition = mSize; // сохраняем 00455 mCurrent = erase(iter, mEnd); 00456 mSave = mEnd = mText.end(); 00457 mSize = mPosition; // восстанавливаем 00458 return; 00459 } 00460 00461 // увеличиваем 00462 mSize ++; 00463 } 00464 } 00465 00466 void TextIterator::cutMaxLengthFromBeginning(size_t _max) 00467 { 00468 // узнаем размер без тегов 00469 size_t size = getSize(); 00470 if (size <= _max) return; 00471 00472 // разница 00473 size_t diff = size - _max; 00474 00475 // последний цвет 00476 UString::iterator iter_colour = mEnd; 00477 00478 // теперь пройдем от начала и узнаем реальную позицию разницы 00479 UString::iterator iter = mText.begin(); 00480 for (; iter != mEnd; ++iter) 00481 { 00482 if ((*iter) == L'#') 00483 { 00484 UString::iterator save = iter; 00485 00486 // следующий символ 00487 ++ iter; 00488 if (iter == mEnd) break; 00489 00490 // тэг цвета 00491 if ((*iter) != L'#') 00492 { 00493 // остальные 5 символов цвета 00494 for (size_t pos = 0; pos < 5; pos++) 00495 { 00496 ++ iter; 00497 if (iter == mEnd) 00498 { 00499 -- iter; 00500 break; 00501 } 00502 } 00503 // сохраняем цвет 00504 iter_colour = save; 00505 } 00506 continue; 00507 } 00508 // обычный символ был 00509 if (diff == 0) break; 00510 -- diff; 00511 } 00512 00513 UString colour; 00514 // если бы цвет, то вставляем назад 00515 if (iter_colour != mEnd) 00516 { 00517 colour.append(iter_colour, iter_colour + size_t(7)); 00518 } 00519 00520 mCurrent = erase(mText.begin(), iter); 00521 mEnd = mText.end(); 00522 mSave = mText.end(); //FIXME 00523 mPosition = 0; 00524 mSize = _max; 00525 00526 if ( ! colour.empty() ) setTagColour(colour); 00527 00528 } 00529 00530 void TextIterator::clearTagColour() 00531 { 00532 if (mCurrent == mEnd) return; 00533 00534 UString::iterator iter = mCurrent; 00535 UString colour; 00536 // нам нужен последний цвет 00537 while (getTagColour(colour, iter)) 00538 { 00539 // обязательно обновляем итераторы 00540 iter = mCurrent = erase(mCurrent, iter); 00541 mEnd = mText.end(); 00542 } 00543 } 00544 00545 size_t TextIterator::getPosition() const 00546 { 00547 return mPosition; 00548 } 00549 00550 const UString& TextIterator::getText() const 00551 { 00552 return mText; 00553 } 00554 00555 void TextIterator::clearText() 00556 { 00557 clear(); 00558 } 00559 00560 UString TextIterator::getTextNewLine() 00561 { 00562 return L"\n"; 00563 } 00564 00565 void TextIterator::normaliseNewLine(UString& _text) 00566 { 00567 for (size_t index = 0; index < _text.size(); ++index) 00568 { 00569 Char character = _text[index]; 00570 if ((character == FontCodeType::CR) && 00571 ((index + 1) < _text.size()) && 00572 (_text[index + 1] == FontCodeType::LF)) 00573 { 00574 _text.erase(index, 1); 00575 } 00576 } 00577 } 00578 00579 } // namespace MyGUI