7#include "katetexthistory.h"
8#include "katetextbuffer.h"
14 , m_lastSavedRevision(-1)
15 , m_firstHistoryEntryRevision(0)
20TextHistory::~TextHistory() =
default;
25 return m_buffer.revision();
28void TextHistory::clear()
31 m_lastSavedRevision = -1;
34 m_historyEntries.clear();
35 m_historyEntries.push_back(Entry());
38 m_firstHistoryEntryRevision = revision();
41void TextHistory::setLastSavedRevision()
44 m_lastSavedRevision = revision();
51 entry.type = Entry::WrapLine;
52 entry.line = position.
line();
53 entry.column = position.
column();
57void TextHistory::unwrapLine(
int line,
int oldLineLength)
61 entry.type = Entry::UnwrapLine;
64 entry.oldLineLength = oldLineLength;
68void TextHistory::insertText(
const KTextEditor::Cursor position,
int length,
int oldLineLength)
72 entry.type = Entry::InsertText;
73 entry.line = position.
line();
74 entry.column = position.
column();
75 entry.length = length;
76 entry.oldLineLength = oldLineLength;
84 entry.type = Entry::RemoveText;
88 entry.oldLineLength = oldLineLength;
92void TextHistory::addEntry(
const Entry &entry)
95 Q_ASSERT(!m_historyEntries.empty());
99 if ((m_historyEntries.size() == 1) && !m_historyEntries.front().referenceCounter) {
101 m_firstHistoryEntryRevision = revision() + 1;
104 m_historyEntries.front() = entry;
111 m_historyEntries.push_back(entry);
117 Q_ASSERT(!m_historyEntries.empty());
118 Q_ASSERT(
revision >= m_firstHistoryEntryRevision);
119 Q_ASSERT(
revision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
122 Entry &entry = m_historyEntries[
revision - m_firstHistoryEntryRevision];
123 ++entry.referenceCounter;
129 Q_ASSERT(!m_historyEntries.empty());
130 Q_ASSERT(
revision >= m_firstHistoryEntryRevision);
131 Q_ASSERT(
revision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
134 Entry &entry = m_historyEntries[
revision - m_firstHistoryEntryRevision];
135 Q_ASSERT(entry.referenceCounter);
136 --entry.referenceCounter;
139 if (!entry.referenceCounter) {
141 qint64 unreferencedEdits = 0;
142 for (qint64 i = 0; i + 1 < qint64(m_historyEntries.size()); ++i) {
143 if (m_historyEntries[i].referenceCounter) {
152 if (unreferencedEdits > 0) {
154 m_historyEntries.erase(m_historyEntries.begin(), m_historyEntries.begin() + unreferencedEdits);
157 m_firstHistoryEntryRevision += unreferencedEdits;
162void TextHistory::Entry::transformCursor(
int &cursorLine,
int &cursorColumn,
bool moveOnInsert)
const
167 if (line > cursorLine) {
176 if (cursorLine == line) {
178 if (cursorColumn <= column) {
179 if (cursorColumn < column || !moveOnInsert) {
185 cursorColumn = cursorColumn - column;
195 if (cursorLine == line) {
196 cursorColumn += oldLineLength;
206 if (cursorLine != line) {
211 if (cursorColumn <= column) {
212 if (cursorColumn < column || !moveOnInsert) {
218 if (cursorColumn <= oldLineLength) {
219 cursorColumn += length;
223 else if (cursorColumn < oldLineLength + length) {
224 cursorColumn = oldLineLength + length;
232 if (cursorLine != line) {
237 if (cursorColumn <= column) {
242 if (cursorColumn <= column + length) {
243 cursorColumn = column;
245 cursorColumn -= length;
256void TextHistory::Entry::reverseTransformCursor(
int &cursorLine,
int &cursorColumn,
bool moveOnInsert)
const
263 if (cursorLine <= line) {
268 if (cursorLine == line + 1) {
270 cursorColumn = cursorColumn + column;
280 if (cursorLine < line - 1) {
285 if (cursorLine == line - 1) {
287 if (cursorColumn <= oldLineLength) {
288 if (cursorColumn < oldLineLength || !moveOnInsert) {
293 cursorColumn -= oldLineLength;
303 if (cursorLine != line) {
308 if (cursorColumn <= column) {
313 if (cursorColumn - length < column) {
314 cursorColumn = column;
316 cursorColumn -= length;
324 if (cursorLine != line) {
329 if (cursorColumn <= column) {
330 if (cursorColumn < column || !moveOnInsert) {
336 if (cursorColumn <= oldLineLength) {
337 cursorColumn += length;
341 else if (cursorColumn < oldLineLength + length) {
342 cursorColumn = oldLineLength + length;
355 if (fromRevision == -1) {
359 if (toRevision == -1) {
364 if (fromRevision == toRevision) {
369 Q_ASSERT(!m_historyEntries.empty());
370 Q_ASSERT(fromRevision != toRevision);
371 Q_ASSERT(fromRevision >= m_firstHistoryEntryRevision);
372 Q_ASSERT(fromRevision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
373 Q_ASSERT(toRevision >= m_firstHistoryEntryRevision);
374 Q_ASSERT(toRevision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
380 if (toRevision > fromRevision) {
381 for (
int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) {
382 const Entry &entry = m_historyEntries.at(rev);
383 entry.transformCursor(line, column, moveOnInsert);
386 for (
int rev = fromRevision - m_firstHistoryEntryRevision; rev >= (toRevision - m_firstHistoryEntryRevision + 1); --rev) {
387 const Entry &entry = m_historyEntries.at(rev);
388 entry.reverseTransformCursor(line, column, moveOnInsert);
401 if (invalidateIfEmpty && range.
end() <= range.
start()) {
407 if (fromRevision == -1) {
411 if (toRevision == -1) {
416 if (fromRevision == toRevision) {
421 Q_ASSERT(!m_historyEntries.empty());
422 Q_ASSERT(fromRevision != toRevision);
423 Q_ASSERT(fromRevision >= m_firstHistoryEntryRevision);
424 Q_ASSERT(fromRevision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
425 Q_ASSERT(toRevision >= m_firstHistoryEntryRevision);
426 Q_ASSERT(toRevision < (m_firstHistoryEntryRevision + qint64(m_historyEntries.size())));
433 int endLine = range.
end().
line();
440 if (toRevision > fromRevision) {
441 for (
int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) {
442 const Entry &entry = m_historyEntries.at(rev);
444 entry.transformCursor(startLine, startColumn, moveOnInsertStart);
446 entry.transformCursor(endLine, endColumn, moveOnInsertEnd);
449 if (endLine < startLine || (endLine == startLine && endColumn <= startColumn)) {
450 if (invalidateIfEmpty) {
456 endColumn = startColumn;
461 for (
int rev = fromRevision - m_firstHistoryEntryRevision; rev >= (toRevision - m_firstHistoryEntryRevision + 1); --rev) {
462 const Entry &entry = m_historyEntries.at(rev);
464 entry.reverseTransformCursor(startLine, startColumn, moveOnInsertStart);
466 entry.reverseTransformCursor(endLine, endColumn, moveOnInsertEnd);
469 if (endLine < startLine || (endLine == startLine && endColumn <= startColumn)) {
470 if (invalidateIfEmpty) {
476 endColumn = startColumn;
The Cursor represents a position in a Document.
constexpr int column() const noexcept
Retrieve the column on which this cursor is situated.
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
InsertBehavior
Insert behavior of this cursor, should it stay if text is insert at its position or should it move.
@ MoveOnInsert
move on insert
QFlags< InsertBehavior > InsertBehaviors
Stores a combination of InsertBehavior values.
EmptyBehavior
Behavior of range if it becomes empty.
@ InvalidateIfEmpty
invalidate range, if it becomes empty
@ ExpandRight
Expand to encapsulate new characters to the right of the range.
@ ExpandLeft
Expand to encapsulate new characters to the left of the range.
An object representing a section of text, from one Cursor to another.
constexpr Cursor end() const noexcept
Get the end position of this range.
constexpr Cursor start() const noexcept
Get the start position of this range.
void setRange(Range range) noexcept
Set the start and end cursors to range.start() and range.end() respectively.
static constexpr Range invalid() noexcept
Returns an invalid range.
Class representing a text buffer.
void unlockRevision(qint64 revision)
Release a revision.
qint64 revision() const
Current revision, just relay the revision of the buffer.
void transformCursor(int &line, int &column, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision=-1)
Transform a cursor from one revision to an other.
void transformRange(KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors, KTextEditor::MovingRange::EmptyBehavior emptyBehavior, qint64 fromRevision, qint64 toRevision=-1)
Transform a range from one revision to an other.
void lockRevision(qint64 revision)
Lock a revision, this will keep it around until released again.