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