MyGUI_TextIterator.cpp
Go to the documentation of this file.
/*
* This source file is part of MyGUI. For the latest info, see http://mygui.info/
* Distributed under the MIT License
* (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_TextIterator.h"
namespace MyGUI
{
TextIterator::TextIterator() :
mPosition(0),
mSize(ITEM_NONE),
mFirst(true),
mHistory(nullptr)
{
}
TextIterator::TextIterator(const UString& _text, VectorChangeInfo* _history) :
mText(_text.asUTF32()),
mCurrent(mText.begin()),
mEnd(mText.end()),
mSave(mEnd),
mPosition(0),
mSize(ITEM_NONE),
mFirst(true),
mHistory(_history)
{
}
bool TextIterator::moveNext()
{
if (mCurrent == mEnd)
return false;
if (mFirst)
{
mFirst = false;
return true;
}
// jump to next character, skipping tags (#)
for (UString::utf32string::iterator iter = mCurrent; iter != mEnd; ++iter)
{
if ((*iter) == L'#')
{
// следующий символ
++iter;
if (iter == mEnd)
{
mCurrent = mEnd;
return false;
}
// две решетки подряд
if ((*iter) == L'#')
{
// следующий символ
mPosition++;
++iter;
if (iter == mEnd)
{
mCurrent = mEnd;
return false;
}
// указатель на следующий символ
mCurrent = iter;
return true;
}
// остальные 5 символов цвета
for (size_t pos = 0; pos < 5; pos++)
{
// следующий символ
++iter;
if (iter == mEnd)
{
mCurrent = mEnd;
return false;
}
}
}
else
{
// обыкновенный символ
mPosition++;
++iter;
if (iter == mEnd)
{
mCurrent = mEnd;
return false;
}
// указатель на следующий символ
mCurrent = iter;
return true;
}
}
return false;
}
// возвращает цвет
bool TextIterator::getTagColour(UString& _colour) const
{
if (mCurrent == mEnd)
return false;
UString::utf32string::iterator iter = mCurrent;
// нам нужен последний цвет
bool ret = false;
while (getTagColour(_colour, iter))
{
ret = true;
}
return ret;
}
bool TextIterator::setTagColour(const Colour& _colour)
{
if (mCurrent == mEnd)
return false;
clearTagColour();
if (mCurrent == mEnd)
return false;
const size_t SIZE = 16;
wchar_t buff[SIZE];
#ifdef __MINGW32__
swprintf(
buff,
L"#%.2X%.2X%.2X\0",
(int)(_colour.red * 255),
(int)(_colour.green * 255),
(int)(_colour.blue * 255));
#else
swprintf(
buff,
SIZE,
L"#%.2X%.2X%.2X\0",
(int)(_colour.red * 255),
(int)(_colour.green * 255),
(int)(_colour.blue * 255));
#endif
UString tmpStr = UString(buff);
insert(mCurrent, tmpStr.asUTF32());
return true;
}
bool TextIterator::setTagColour(const UString::utf32string& _colour)
{
if (mCurrent == mEnd)
return false;
clearTagColour();
if (mCurrent == mEnd)
return false;
// check if it looks like a colour tag
if ((_colour.size() != 7) || (_colour.find(L'#', 1) != MyGUI::UString::npos))
return false;
insert(mCurrent, _colour);
return true;
}
bool TextIterator::setTagColour(const UString& _colour)
{
return setTagColour(_colour.asUTF32());
}
// возвращает размер строки
size_t TextIterator::getSize() const
{
if (mSize != ITEM_NONE)
return mSize;
mSize = mPosition;
for (UString::utf32string::const_iterator iter = mCurrent; iter != mEnd; ++iter)
{
if ((*iter) == L'#')
{
// следующий символ
++iter;
if (iter == mEnd)
break;
// тэг цвета
if ((*iter) != L'#')
{
// остальные 5 символов цвета
for (size_t pos = 0; pos < 5; pos++)
{
++iter;
if (iter == mEnd)
{
--iter;
break;
}
}
continue;
}
}
// обыкновенный символ
mSize++;
}
return mSize;
}
// возвращает текст без тегов
UString TextIterator::getOnlyText(const UString& _text)
{
UString::utf32string ret;
UString::utf32string text(_text.asUTF32());
ret.reserve(text.size());
UString::utf32string::const_iterator end = text.end();
for (UString::utf32string::const_iterator iter = text.begin(); iter != end; ++iter)
{
if ((*iter) == L'#')
{
// следующий символ
++iter;
if (iter == end)
break;
// тэг цвета
if ((*iter) != L'#')
{
// остальные 5 символов цвета
for (size_t pos = 0; pos < 5; pos++)
{
++iter;
if (iter == end)
{
--iter;
break;
}
}
continue;
}
}
// обыкновенный символ
ret.push_back(*iter);
}
return UString(ret);
}
// возвращает цвет
bool TextIterator::getTagColour(UString& _colour, UString::utf32string::iterator& _iter) const
{
if ((_iter == mEnd) || ((*_iter) != L'#'))
return false;
// следующий символ
++_iter;
if ((_iter == mEnd) || ((*_iter) == L'#'))
return false;
// берем цвет
wchar_t buff[16] = L"#FFFFFF\0";
buff[1] = (wchar_t)(*_iter);
for (size_t pos = 2; pos < 7; pos++)
{
++_iter;
if (_iter == mEnd)
return false;
buff[pos] = (wchar_t)(*_iter);
}
// ставим на следующий тег или символ
++_iter;
// возвращаем цвет
_colour = buff;
return true;
}
void TextIterator::clearNewLine(UString& _text)
{
for (UString::iterator iter = _text.begin(); iter != _text.end(); iter.moveNext())
{
auto character = iter.getCharacter();
if (character == FontCodeType::NEL || character == FontCodeType::CR || character == FontCodeType::LF)
{
(*iter) = FontCodeType::Space;
}
}
}
bool TextIterator::saveStartPoint()
{
if (mCurrent == mEnd)
return false;
mSave = mCurrent;
return true;
}
UString TextIterator::getFromStart() const
{
if (mSave == mEnd)
return {};
size_t start = mSave - mText.begin();
return UString(mText.substr(start, mCurrent - mText.begin() - start));
}
bool TextIterator::eraseFromStart()
{
if (mSave == mEnd)
return false;
mCurrent = erase(mSave, mCurrent);
mSave = mEnd = mText.end();
return true;
}
void TextIterator::insertText(const UString& _insert, bool _multiLine)
{
UString text = _insert;
normaliseNewLine(text);
if (!_multiLine)
clearNewLine(text);
insert(mCurrent, text.asUTF32());
}
void TextIterator::setText(const UString& _text, bool _multiLine)
{
// сначала все очищаем
clear();
// а теперь вставляем
UString text = _text;
// нормализуем
normaliseNewLine(text);
if (!_multiLine)
clearNewLine(text);
insert(mCurrent, text.asUTF32());
}
UString TextIterator::getTextCharInfo(Char _char)
{
if (_char == L'#')
return L"##";
wchar_t buff[16] = L"_\0";
buff[0] = (wchar_t)_char;
return buff;
}
UString TextIterator::convertTagColour(const Colour& _colour)
{
const size_t SIZE = 16;
wchar_t buff[SIZE];
//FIXME
#ifdef __MINGW32__
swprintf(
buff,
L"#%.2X%.2X%.2X\0",
(int)(_colour.red * 255),
(int)(_colour.green * 255),
(int)(_colour.blue * 255));
#else
swprintf(
buff,
SIZE,
L"#%.2X%.2X%.2X\0",
(int)(_colour.red * 255),
(int)(_colour.green * 255),
(int)(_colour.blue * 255));
#endif
return buff;
}
UString TextIterator::toTagsString(const UString& _text)
{
// преобразуем в строку с тегами
UString text(_text);
for (UString::iterator iter = text.begin(); iter != text.end(); iter.moveNext())
{
// потом переделать через TextIterator чтобы отвязать понятие тег от эдита
if (L'#' == (*iter))
iter = text.insert(iter.moveNext(), L'#');
}
return text;
}
void TextIterator::insert(UString::utf32string::iterator& _start, const UString::utf32string& _insert)
{
// сбрасываем размер
mSize = ITEM_NONE;
// записываем в историю
if (mHistory)
mHistory->push_back(TextCommandInfo(_insert, _start - mText.begin(), TextCommandInfo::COMMAND_INSERT));
// запоминаем позицию итератора
size_t pos = _start - mText.begin();
size_t pos_save = (mSave == mEnd) ? ITEM_NONE : _start - mText.begin();
// непосредственно вставляем
mText.insert(_start, _insert.begin(), _insert.end());
// возвращаем итераторы
_start = mText.begin() + pos;
mEnd = mText.end();
(pos_save == ITEM_NONE) ? mSave = mEnd : mSave = mText.begin() + pos_save;
}
UString::utf32string::iterator TextIterator::erase(
UString::utf32string::iterator _start,
UString::utf32string::iterator _end)
{
// сбрасываем размер
mSize = ITEM_NONE;
// сохраняем в историю
size_t start = _start - mText.begin();
if (mHistory)
mHistory->push_back(
TextCommandInfo(mText.substr(start, _end - _start), start, TextCommandInfo::COMMAND_ERASE));
// возвращаем итератор
return mText.erase(_start, _end);
}
void TextIterator::clear()
{
if (mText.empty())
return;
// записываем в историю
if (mHistory)
mHistory->push_back(TextCommandInfo(mText, 0, TextCommandInfo::COMMAND_ERASE));
// все сбрасываем
mText.clear();
mCurrent = mText.begin();
mEnd = mSave = mText.end();
mSize = ITEM_NONE;
}
void TextIterator::cutMaxLength(size_t _max)
{
if ((mSize != ITEM_NONE) && (mSize <= _max))
return;
if (mPosition > _max)
{
// придется считать сначала
mSize = mPosition = 0;
mCurrent = mText.begin();
mEnd = mSave = mText.end();
}
mSize = mPosition;
for (UString::utf32string::iterator iter = mCurrent; iter != mEnd; ++iter)
{
if ((*iter) == L'#')
{
// следующий символ
++iter;
if (iter == mEnd)
break;
// тэг цвета
if ((*iter) != L'#')
{
// остальные 5 символов цвета
for (size_t pos = 0; pos < 5; pos++)
{
++iter;
if (iter == mEnd)
{
--iter;
break;
}
}
continue;
}
}
// проверяем и обрезаем
if (mSize == _max)
{
mPosition = mSize; // сохраняем
mCurrent = erase(iter, mEnd);
mSave = mEnd = mText.end();
mSize = mPosition; // восстанавливаем
return;
}
// увеличиваем
mSize++;
}
}
void TextIterator::cutMaxLengthFromBeginning(size_t _max)
{
// узнаем размер без тегов
size_t size = getSize();
if (size <= _max)
return;
// разница
size_t diff = size - _max;
// последний цвет
UString::utf32string::iterator iter_colour = mEnd;
// теперь пройдем от начала и узнаем реальную позицию разницы
UString::utf32string::iterator iter = mText.begin();
for (; iter != mEnd; ++iter)
{
if ((*iter) == L'#')
{
UString::utf32string::iterator save = iter;
// следующий символ
++iter;
if (iter == mEnd)
break;
// тэг цвета
if ((*iter) != L'#')
{
// остальные 5 символов цвета
for (size_t pos = 0; pos < 5; pos++)
{
++iter;
if (iter == mEnd)
{
--iter;
break;
}
}
// сохраняем цвет
iter_colour = save;
}
continue;
}
// обычный символ был
if (diff == 0)
break;
--diff;
}
UString::utf32string colour;
// если бы цвет, то вставляем назад
if (iter_colour != mEnd)
{
colour.append(iter_colour, iter_colour + size_t(7));
}
mCurrent = erase(mText.begin(), iter);
mEnd = mText.end();
mSave = mText.end(); //FIXME
mPosition = 0;
mSize = _max;
if (!colour.empty())
setTagColour(colour);
}
void TextIterator::clearTagColour()
{
if (mCurrent == mEnd)
return;
UString::utf32string::iterator iter = mCurrent;
UString colour;
// нам нужен последний цвет
while (getTagColour(colour, iter))
{
// обязательно обновляем итераторы
iter = mCurrent = erase(mCurrent, iter);
mEnd = mText.end();
}
}
size_t TextIterator::getPosition() const
{
return mPosition;
}
UString TextIterator::getText() const
{
return UString(mText);
}
void TextIterator::clearText()
{
clear();
}
UString TextIterator::getTextNewLine()
{
return L"\n";
}
void TextIterator::normaliseNewLine(UString& _text)
{
for (size_t index = 0; index < _text.size(); ++index)
{
Char character = _text[index];
if ((character == FontCodeType::CR) && ((index + 1) < _text.size()) &&
(_text[index + 1] == FontCodeType::LF))
{
_text.erase(index, 1);
}
}
}
} // namespace MyGUI
MyGUI_Precompiled.h
MyGUI_TextIterator.h
MyGUI::TextIterator::eraseFromStart
bool eraseFromStart()
Definition MyGUI_TextIterator.cpp:317
MyGUI::TextIterator::getOnlyText
static UString getOnlyText(const UString &_text)
Definition MyGUI_TextIterator.cpp:219
MyGUI::TextIterator::clearTagColour
void clearTagColour()
Definition MyGUI_TextIterator.cpp:572
MyGUI::TextIterator::clearNewLine
void clearNewLine(UString &_text)
Definition MyGUI_TextIterator.cpp:289
MyGUI::TextIterator::getText
UString getText() const
Definition MyGUI_TextIterator.cpp:593
MyGUI::TextIterator::getTextNewLine
static UString getTextNewLine()
Definition MyGUI_TextIterator.cpp:603
MyGUI::TextIterator::getTextCharInfo
static UString getTextCharInfo(Char _char)
Definition MyGUI_TextIterator.cpp:355
MyGUI::TextIterator::cutMaxLength
void cutMaxLength(size_t _max)
Definition MyGUI_TextIterator.cpp:450
MyGUI::TextIterator::setTagColour
bool setTagColour(const Colour &_colour)
Definition MyGUI_TextIterator.cpp:123
MyGUI::TextIterator::moveNext
bool moveNext()
Definition MyGUI_TextIterator.cpp:33
MyGUI::TextIterator::getFromStart
UString getFromStart() const
Definition MyGUI_TextIterator.cpp:309
MyGUI::TextIterator::convertTagColour
static UString convertTagColour(const Colour &_colour)
Definition MyGUI_TextIterator.cpp:364
MyGUI::TextIterator::clearText
void clearText()
Definition MyGUI_TextIterator.cpp:598
MyGUI::TextIterator::saveStartPoint
bool saveStartPoint()
Definition MyGUI_TextIterator.cpp:301
MyGUI::TextIterator::toTagsString
static UString toTagsString(const UString &_text)
Definition MyGUI_TextIterator.cpp:388
MyGUI::TextIterator::cutMaxLengthFromBeginning
void cutMaxLengthFromBeginning(size_t _max)
Definition MyGUI_TextIterator.cpp:505
MyGUI::TextIterator::setText
void setText(const UString &_text, bool _multiLine)
Definition MyGUI_TextIterator.cpp:338
MyGUI::TextIterator::getPosition
size_t getPosition() const
Definition MyGUI_TextIterator.cpp:588
MyGUI::TextIterator::getSize
size_t getSize() const
Definition MyGUI_TextIterator.cpp:179
MyGUI::TextIterator::insertText
void insertText(const UString &_insert, bool _multiLine)
Definition MyGUI_TextIterator.cpp:326
MyGUI::TextIterator::getTagColour
bool getTagColour(UString &_colour) const
Definition MyGUI_TextIterator.cpp:106
MyGUI::UString::_fwd_iterator::moveNext
_fwd_iterator & moveNext()
advances to the next Unicode character, honoring surrogate pairs in the UTF-16 stream
Definition MyGUI_UString.cpp:180
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition MyGUI_UString.h:144
MyGUI::UString::insert
iterator insert(iterator i, const code_point &ch)
inserts ch before the code point denoted by i
Definition MyGUI_UString.cpp:1042
MyGUI::UString::size
size_type size() const
Returns the number of code points in the current string.
Definition MyGUI_UString.cpp:556
MyGUI::UString::asUTF32
const utf32string & asUTF32() const
returns the current string in UTF-32 form within a utf32string
Definition MyGUI_UString.cpp:685
MyGUI::UString::utf32string
std::basic_string< unicode_char > utf32string
string type used for returning UTF-32 formatted data
Definition MyGUI_UString.h:177
MyGUI::UString::erase
iterator erase(iterator loc)
removes the code point pointed to by loc, returning an iterator to the next character
Definition MyGUI_UString.cpp:1161
MyGUI::UString::end
iterator end()
returns an iterator just past the end of the string
Definition MyGUI_UString.cpp:783
MyGUI::UString::npos
static const size_type npos
the usual constant representing: not found, no limit, etc
Definition MyGUI_UString.h:163
MyGUI::UString::iterator
_fwd_iterator iterator
iterator
Definition MyGUI_UString.h:407
MyGUI::UString::begin
iterator begin()
returns an iterator to the first element of the string
Definition MyGUI_UString.cpp:767
MyGUI::FontCodeType::CR
@ CR
Definition MyGUI_FontData.h:23
MyGUI::FontCodeType::NEL
@ NEL
Definition MyGUI_FontData.h:25
MyGUI::FontCodeType::Space
@ Space
Definition MyGUI_FontData.h:24
MyGUI::FontCodeType::LF
@ LF
Definition MyGUI_FontData.h:22
MyGUI
Definition MyGUI_ActionController.h:15
MyGUI::VectorChangeInfo
std::vector< TextCommandInfo > VectorChangeInfo
Definition MyGUI_TextChangeHistory.h:58
MyGUI::Char
unsigned int Char
Definition MyGUI_Types.h:50
MyGUI::ITEM_NONE
constexpr size_t ITEM_NONE
Definition MyGUI_Macros.h:19
MyGUI::Colour
Definition MyGUI_Colour.h:17
MyGUI::Colour::green
float green
Definition MyGUI_Colour.h:49
MyGUI::Colour::blue
float blue
Definition MyGUI_Colour.h:50
MyGUI::Colour::red
float red
Definition MyGUI_Colour.h:48
MyGUI::TextCommandInfo
Definition MyGUI_TextChangeHistory.h:20
MyGUI::TextCommandInfo::COMMAND_INSERT
@ COMMAND_INSERT
Definition MyGUI_TextChangeHistory.h:24
MyGUI::TextCommandInfo::COMMAND_ERASE
@ COMMAND_ERASE
Definition MyGUI_TextChangeHistory.h:25