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