diff --git a/src/buffer/katetextblock.cpp b/src/buffer/katetextblock.cpp --- a/src/buffer/katetextblock.cpp +++ b/src/buffer/katetextblock.cpp @@ -21,6 +21,8 @@ #include "katetextblock.h" #include "katetextbuffer.h" +#include + namespace Kate { @@ -149,7 +151,8 @@ } // move all cursors on the line which has the text inserted - QSet changedRanges; + // remember all ranges modified, optimize for the standard case of a few ranges + QVarLengthArray changedRanges; for (TextCursor *cursor : qAsConst(m_cursors)) { // skip cursors on lines in front of the wrapped one! if (cursor->lineInBlock() < line) { @@ -180,9 +183,11 @@ cursor->m_column -= position.column(); } - // remember range, if any - if (cursor->kateRange()) { - changedRanges.insert(cursor->kateRange()); + // remember range, if any, avoid double insert + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired()) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } @@ -245,16 +250,19 @@ } // move all cursors because of the unwrapped line - QSet changedRanges; + // remember all ranges modified, optimize for the standard case of a few ranges + QVarLengthArray changedRanges; for (TextCursor *cursor : qAsConst(m_cursors)) { // this is the unwrapped line if (cursor->lineInBlock() == 0) { // patch column cursor->m_column += oldSizeOfPreviousLine; - // remember range, if any - if (cursor->kateRange()) { - changedRanges.insert(cursor->kateRange()); + // remember range, if any, avoid double insert + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired()) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } } @@ -267,9 +275,11 @@ cursor->m_block = this; m_cursors.insert(cursor); - // remember range, if any - if (cursor->kateRange()) { - changedRanges.insert(cursor->kateRange()); + // remember range, if any, avoid double insert + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired()) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } else { newPreviousCursors.insert(cursor); @@ -331,7 +341,8 @@ } // move all cursors because of the unwrapped line - QSet changedRanges; + // remember all ranges modified, optimize for the standard case of a few ranges + QVarLengthArray changedRanges; for (TextCursor *cursor : qAsConst(m_cursors)) { // skip cursors in lines in front of removed one if (cursor->lineInBlock() < line) { @@ -347,9 +358,11 @@ // patch line of cursor cursor->m_line--; - // remember range, if any - if (cursor->kateRange()) { - changedRanges.insert(cursor->kateRange()); + // remember range, if any, avoid double insert + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired()) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } @@ -392,7 +405,8 @@ } // move all cursors on the line which has the text inserted - QSet changedRanges; + // remember all ranges modified, optimize for the standard case of a few ranges + QVarLengthArray changedRanges; for (TextCursor *cursor : qAsConst(m_cursors)) { // skip cursors not on this line! if (cursor->lineInBlock() != line) { @@ -416,9 +430,12 @@ cursor->m_column = textOfLine.size(); } + // remember range, if any, avoid double insert // we only need to trigger checkValidity later if the range has feedback or might be invalidated - if (cursor->kateRange() && (cursor->kateRange()->feedback() || cursor->kateRange()->start().line() == cursor->kateRange()->end().line())) { - changedRanges.insert(cursor->kateRange()); + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired() && (range->feedback() || range->start().line() == range->end().line())) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } @@ -466,7 +483,8 @@ } // move all cursors on the line which has the text removed - QSet changedRanges; + // remember all ranges modified, optimize for the standard case of a few ranges + QVarLengthArray changedRanges; for (TextCursor *cursor : qAsConst(m_cursors)) { // skip cursors not on this line! if (cursor->lineInBlock() != line) { @@ -485,9 +503,12 @@ cursor->m_column -= (range.end().column() - range.start().column()); } + // remember range, if any, avoid double insert // we only need to trigger checkValidity later if the range has feedback or might be invalidated - if (cursor->kateRange() && (cursor->kateRange()->feedback() || cursor->kateRange()->start().line() == cursor->kateRange()->end().line())) { - changedRanges.insert(cursor->kateRange()); + auto range = cursor->kateRange(); + if (range && !range->isValidityCheckRequired() && (range->feedback() || range->start().line() == range->end().line())) { + range->setValidityCheckRequired(); + changedRanges.push_back(range); } } diff --git a/src/buffer/katetextrange.h b/src/buffer/katetextrange.h --- a/src/buffer/katetextrange.h +++ b/src/buffer/katetextrange.h @@ -284,12 +284,12 @@ /** * no copy constructor, don't allow this to be copied. */ - TextRange(const TextRange &); + TextRange(const TextRange &) = delete; /** * no assignment operator, no copying around. */ - TextRange &operator= (const TextRange &); + TextRange &operator= (const TextRange &) = delete; /** * Check if range is valid, used by constructor and setRange. @@ -313,6 +313,23 @@ */ void fixLookup(int oldStartLine, int oldEndLine, int startLine, int endLine); + /** + * Mark this range for later validity checking. + */ + void setValidityCheckRequired() + { + m_isCheckValidityRequired = true; + } + + /** + * Does this range need validity checking? + * @return is checking required? + */ + bool isValidityCheckRequired() const + { + return m_isCheckValidityRequired; + } + private: /** * parent text buffer @@ -359,6 +376,13 @@ * Will this range invalidate itself if it becomes empty? */ bool m_invalidateIfEmpty; + + /** + * Should this range be validated? + * Used by KateTextBlock to avoid multiple updates without costly hashing. + * Reset by checkValidity(). + */ + bool m_isCheckValidityRequired = false; }; } diff --git a/src/buffer/katetextrange.cpp b/src/buffer/katetextrange.cpp --- a/src/buffer/katetextrange.cpp +++ b/src/buffer/katetextrange.cpp @@ -181,6 +181,11 @@ void TextRange::checkValidity(int oldStartLine, int oldEndLine, bool notifyAboutChange) { + /** + * in any case: reset the flag, to avoid multiple runs + */ + m_isCheckValidityRequired = false; + /** * check if any cursor is invalid or the range is zero size and it should be invalidated then */