• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

MyGUI_TextIterator.cpp

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

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1