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