Fix modifications tracking with skip block.
This commit is contained in:
parent
9eb9fcf043
commit
8915f5d40d
3 changed files with 63 additions and 31 deletions
|
|
@ -673,9 +673,12 @@ bool String::updateSkipBlock(int width, int height) {
|
|||
if (block->f_width().toInt() == width && block->height() == height) {
|
||||
return false;
|
||||
}
|
||||
_text.resize(block->position());
|
||||
const auto size = block->position();
|
||||
_text.resize(size);
|
||||
_blocks.pop_back();
|
||||
removeModificationsAfter(size);
|
||||
} else if (_endsWithQuote) {
|
||||
insertModifications(_text.size(), 1);
|
||||
_text.push_back(QChar::LineFeed);
|
||||
_blocks.push_back(Block::Newline(
|
||||
_st->font,
|
||||
|
|
@ -687,6 +690,7 @@ bool String::updateSkipBlock(int width, int height) {
|
|||
0));
|
||||
_skipBlockAddedNewline = true;
|
||||
}
|
||||
insertModifications(_text.size(), 1);
|
||||
_text.push_back('_');
|
||||
_blocks.push_back(Block::Skip(
|
||||
_st->font,
|
||||
|
|
@ -704,18 +708,65 @@ bool String::removeSkipBlock() {
|
|||
if (_blocks.empty() || _blocks.back()->type() != TextBlockType::Skip) {
|
||||
return false;
|
||||
} else if (_skipBlockAddedNewline) {
|
||||
_text.resize(_blocks.back()->position() - 1);
|
||||
const auto size = _blocks.back()->position() - 1;
|
||||
_text.resize(size);
|
||||
_blocks.pop_back();
|
||||
_blocks.pop_back();
|
||||
_skipBlockAddedNewline = false;
|
||||
removeModificationsAfter(size);
|
||||
} else {
|
||||
_text.resize(_blocks.back()->position());
|
||||
const auto size = _blocks.back()->position();
|
||||
_text.resize(size);
|
||||
_blocks.pop_back();
|
||||
removeModificationsAfter(size);
|
||||
}
|
||||
recountNaturalSize(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void String::insertModifications(int position, int delta) {
|
||||
auto &modifications = ensureExtended()->modifications;
|
||||
auto i = end(modifications);
|
||||
while (i != begin(modifications) && (--i)->position >= position) {
|
||||
if (i->position < position) {
|
||||
break;
|
||||
} else if (delta > 0) {
|
||||
++i->position;
|
||||
} else if (i->position == position) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != end(modifications) && i->position == position) {
|
||||
++i->skipped;
|
||||
} else {
|
||||
modifications.insert(i, {
|
||||
.position = position,
|
||||
.skipped = uint16(delta < 0 ? (-delta) : 0),
|
||||
.added = (delta > 0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void String::removeModificationsAfter(int size) {
|
||||
if (!_extended) {
|
||||
return;
|
||||
}
|
||||
auto &modifications = _extended->modifications;
|
||||
for (auto i = end(modifications); i != begin(modifications);) {
|
||||
--i;
|
||||
if (i->position > size) {
|
||||
i = modifications.erase(i);
|
||||
} else if (i->position == size) {
|
||||
i->added = false;
|
||||
if (!i->skipped) {
|
||||
i = modifications.erase(i);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int String::countWidth(int width, bool breakEverywhere) const {
|
||||
if (QFixed(width) >= _maxWidth) {
|
||||
return _maxWidth;
|
||||
|
|
|
|||
|
|
@ -407,6 +407,8 @@ private:
|
|||
bool breakEverywhere,
|
||||
Callback callback) const;
|
||||
|
||||
void insertModifications(int position, int delta);
|
||||
void removeModificationsAfter(int size);
|
||||
void recountNaturalSize(
|
||||
bool initial,
|
||||
Qt::LayoutDirection optionsDir = Qt::LayoutDirectionAuto);
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ void Parser::createBlock(int32 skipBack) {
|
|||
if (_newlineAwaited) {
|
||||
_newlineAwaited = false;
|
||||
if (!newline) {
|
||||
updateModifications(_blockStart, 1);
|
||||
_t->insertModifications(_blockStart, 1);
|
||||
_t->_text.insert(_blockStart, QChar::LineFeed);
|
||||
createBlock(skipBack - length);
|
||||
}
|
||||
|
|
@ -226,7 +226,7 @@ void Parser::createBlock(int32 skipBack) {
|
|||
|
||||
void Parser::createNewlineBlock(bool fromOriginalText) {
|
||||
if (!fromOriginalText) {
|
||||
updateModifications(_t->_text.size(), 1);
|
||||
_t->insertModifications(_t->_text.size(), 1);
|
||||
}
|
||||
_t->_text.push_back(QChar::LineFeed);
|
||||
_allowDiacritic = false;
|
||||
|
|
@ -523,7 +523,9 @@ void Parser::parseCurrentChar() {
|
|||
}
|
||||
|
||||
if (skip) {
|
||||
updateModifications(_t->_text.size(), -1);
|
||||
if (_ptr < _end) {
|
||||
_t->insertModifications(_t->_text.size(), -1);
|
||||
}
|
||||
_ch = 0;
|
||||
_allowDiacritic = false;
|
||||
} else {
|
||||
|
|
@ -572,7 +574,7 @@ void Parser::parseEmojiFromCurrent() {
|
|||
Assert(!_t->_text.isEmpty());
|
||||
const auto last = _t->_text[_t->_text.size() - 1];
|
||||
if (last.unicode() != Emoji::kPostfix) {
|
||||
updateModifications(_t->_text.size(), 1);
|
||||
_t->insertModifications(_t->_text.size(), 1);
|
||||
_t->_text.push_back(QChar(Emoji::kPostfix));
|
||||
++len;
|
||||
}
|
||||
|
|
@ -602,29 +604,6 @@ bool Parser::isLinkEntity(const EntityInText &entity) const {
|
|||
return ranges::find(urls, type) != std::end(urls);
|
||||
}
|
||||
|
||||
void Parser::updateModifications(int index, int delta) {
|
||||
auto &modifications = _t->ensureExtended()->modifications;
|
||||
auto i = end(modifications);
|
||||
while (i != begin(modifications) && (--i)->position >= index) {
|
||||
if (i->position < index) {
|
||||
break;
|
||||
} else if (delta > 0) {
|
||||
++i->position;
|
||||
} else if (i->position == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != end(modifications) && i->position == index) {
|
||||
++i->skipped;
|
||||
} else {
|
||||
modifications.insert(i, {
|
||||
.position = index,
|
||||
.skipped = uint16(delta < 0 ? 1 : 0),
|
||||
.added = (delta > 0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::parse(const TextParseOptions &options) {
|
||||
skipBadEntities();
|
||||
trimSourceRange();
|
||||
|
|
@ -636,7 +615,7 @@ void Parser::parse(const TextParseOptions &options) {
|
|||
_t->_text.reserve(_end - _ptr);
|
||||
|
||||
if (_ptr > _start) {
|
||||
updateModifications(0, -(_ptr - _start));
|
||||
_t->insertModifications(0, -(_ptr - _start));
|
||||
}
|
||||
|
||||
for (; _ptr <= _end; ++_ptr) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue