MyGUI 3.0.1

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         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
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines