Fixed possible crash in Text::String with clickable monospace.
This commit is contained in:
parent
2b87a251cd
commit
d1509436b6
1 changed files with 34 additions and 46 deletions
|
|
@ -255,6 +255,7 @@ private:
|
|||
int32 _flags = 0;
|
||||
uint16 _lnkIndex = 0;
|
||||
uint16 _spoilerIndex = 0;
|
||||
uint16 _monoIndex = 0;
|
||||
EmojiPtr _emoji = nullptr; // current emoji, if current word is an emoji, or zero
|
||||
int32 _blockStart = 0; // offset in result, from which current parsed block is started
|
||||
int32 _diacs = 0; // diac chars skipped without good char
|
||||
|
|
@ -365,14 +366,15 @@ void Parser::createBlock(int32 skipBack) {
|
|||
}
|
||||
}
|
||||
_lastSkipped = false;
|
||||
const auto lnkIndex = _monoIndex ? _monoIndex : _lnkIndex;
|
||||
if (_emoji) {
|
||||
_t->_blocks.push_back(Block::Emoji(_t->_st->font, _t->_text, _blockStart, len, _flags, _lnkIndex, _spoilerIndex, _emoji));
|
||||
_t->_blocks.push_back(Block::Emoji(_t->_st->font, _t->_text, _blockStart, len, _flags, lnkIndex, _spoilerIndex, _emoji));
|
||||
_emoji = nullptr;
|
||||
_lastSkipped = true;
|
||||
} else if (newline) {
|
||||
_t->_blocks.push_back(Block::Newline(_t->_st->font, _t->_text, _blockStart, len, _flags, _lnkIndex, _spoilerIndex));
|
||||
_t->_blocks.push_back(Block::Newline(_t->_st->font, _t->_text, _blockStart, len, _flags, lnkIndex, _spoilerIndex));
|
||||
} else {
|
||||
_t->_blocks.push_back(Block::Text(_t->_st->font, _t->_text, _t->_minResizeWidth, _blockStart, len, _flags, _lnkIndex, _spoilerIndex));
|
||||
_t->_blocks.push_back(Block::Text(_t->_st->font, _t->_text, _t->_minResizeWidth, _blockStart, len, _flags, lnkIndex, _spoilerIndex));
|
||||
}
|
||||
_blockStart += len;
|
||||
blockCreated();
|
||||
|
|
@ -382,7 +384,7 @@ void Parser::createBlock(int32 skipBack) {
|
|||
void Parser::createSkipBlock(int32 w, int32 h) {
|
||||
createBlock();
|
||||
_t->_text.push_back('_');
|
||||
_t->_blocks.push_back(Block::Skip(_t->_st->font, _t->_text, _blockStart++, w, h, _lnkIndex, _spoilerIndex));
|
||||
_t->_blocks.push_back(Block::Skip(_t->_st->font, _t->_text, _blockStart++, w, h, _monoIndex ? _monoIndex : _lnkIndex, _spoilerIndex));
|
||||
blockCreated();
|
||||
}
|
||||
|
||||
|
|
@ -408,6 +410,9 @@ void Parser::finishEntities() {
|
|||
&& _t->_blocks.back()->type() != TextBlockTNewline) {
|
||||
_newlineAwaited = true;
|
||||
}
|
||||
if (IsMono(*flags)) {
|
||||
_monoIndex = 0;
|
||||
}
|
||||
}
|
||||
} else if (const auto lnkIndex = list.back().lnkIndex()) {
|
||||
if (_lnkIndex == *lnkIndex) {
|
||||
|
|
@ -479,24 +484,16 @@ bool Parser::checkEntities() {
|
|||
}
|
||||
}
|
||||
const auto text = QString(entityBegin, entityLength);
|
||||
auto data = QString(2, QChar(0));
|
||||
|
||||
// End of an entity.
|
||||
data[0] = QChar(_waitingEntity->offset() + entityLength);
|
||||
// It is better to trim the text to identify "Sample\n" as inline.
|
||||
const auto trimmed = text.trimmed();
|
||||
const auto isSingleLine = !trimmed.isEmpty()
|
||||
&& ranges::none_of(trimmed, IsNewline);
|
||||
|
||||
{
|
||||
// It is better to trim the text to identify "Sample\n" as inline.
|
||||
const auto trimmed = text.trimmed();
|
||||
const auto isSingleLine = !trimmed.isEmpty()
|
||||
&& ranges::none_of(trimmed, IsNewline);
|
||||
data[1] = QChar(isSingleLine ? 1 : 2);
|
||||
if (isSingleLine) {
|
||||
_monos.push_back({ .text = text, .type = entityType });
|
||||
_monoIndex = _monos.size();
|
||||
}
|
||||
|
||||
_monos.push_back({
|
||||
.text = text,
|
||||
.data = std::move(data),
|
||||
.type = entityType,
|
||||
});
|
||||
} else if (entityType == EntityType::Url
|
||||
|| entityType == EntityType::Email
|
||||
|| entityType == EntityType::Mention
|
||||
|
|
@ -737,7 +734,7 @@ void Parser::trimSourceRange() {
|
|||
|
||||
void Parser::finalize(const TextParseOptions &options) {
|
||||
_t->_links.resize(_maxLnkIndex + _maxShiftedLnkIndex);
|
||||
auto monoLnk = uint16(1);
|
||||
auto currentIndex = uint16(0); // Current the latest index of _t->_links.
|
||||
struct {
|
||||
uint16 mono = 0;
|
||||
uint16 lnk = 0;
|
||||
|
|
@ -753,53 +750,44 @@ void Parser::finalize(const TextParseOptions &options) {
|
|||
}
|
||||
const auto shiftedIndex = block->lnkIndex();
|
||||
if (shiftedIndex <= kStringLinkIndexShift) {
|
||||
if (IsMono(block->flags()) && (monoLnk <= _monos.size())) {
|
||||
{
|
||||
const auto ptr = _monos[monoLnk - 1].data.constData();
|
||||
const auto entityEnd = int(ptr->unicode());
|
||||
const auto singleLine = (int((ptr + 1)->unicode()) == 1);
|
||||
if (!singleLine) {
|
||||
monoLnk++;
|
||||
continue;
|
||||
}
|
||||
if (block->from() >= entityEnd) {
|
||||
monoLnk++;
|
||||
}
|
||||
}
|
||||
const auto monoIndex = _maxLnkIndex
|
||||
+ _maxShiftedLnkIndex
|
||||
+ monoLnk;
|
||||
block->setLnkIndex(monoIndex);
|
||||
if (IsMono(block->flags()) && shiftedIndex) {
|
||||
const auto monoIndex = shiftedIndex;
|
||||
|
||||
if (lastHandlerIndex.mono == monoIndex) {
|
||||
block->setLnkIndex(currentIndex);
|
||||
continue; // Optimization.
|
||||
} else {
|
||||
currentIndex++;
|
||||
}
|
||||
block->setLnkIndex(currentIndex);
|
||||
const auto handler = Integration::Instance().createLinkHandler(
|
||||
_monos[monoLnk - 1],
|
||||
_monos[monoIndex - 1],
|
||||
_context);
|
||||
_t->_links.resize(monoIndex);
|
||||
_t->_links.resize(currentIndex);
|
||||
if (handler) {
|
||||
_t->setLink(monoIndex, handler);
|
||||
_t->setLink(currentIndex, handler);
|
||||
}
|
||||
lastHandlerIndex.mono = monoIndex;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const auto realIndex = (shiftedIndex - kStringLinkIndexShift);
|
||||
const auto index = _maxLnkIndex + realIndex;
|
||||
block->setLnkIndex(index);
|
||||
if (lastHandlerIndex.lnk == index) {
|
||||
if (lastHandlerIndex.lnk == realIndex) {
|
||||
block->setLnkIndex(currentIndex);
|
||||
continue; // Optimization.
|
||||
} else {
|
||||
currentIndex++;
|
||||
}
|
||||
block->setLnkIndex(currentIndex);
|
||||
|
||||
// _t->_links.resize(index);
|
||||
_t->_links.resize(currentIndex);
|
||||
const auto handler = Integration::Instance().createLinkHandler(
|
||||
_links[realIndex - 1],
|
||||
_context);
|
||||
if (handler) {
|
||||
_t->setLink(index, handler);
|
||||
_t->setLink(currentIndex, handler);
|
||||
}
|
||||
lastHandlerIndex.lnk = index;
|
||||
lastHandlerIndex.lnk = realIndex;
|
||||
}
|
||||
_t->_links.squeeze();
|
||||
_t->_spoilers.squeeze();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue