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