designed to fix te kdevelop from git crashes. --- kate/buffer/katetextblock.cpp.orig 2010-07-29 00:05:04.000000000 +0300 +++ kate/buffer/katetextblock.cpp 2010-09-13 22:07:53.000000000 +0200 @@ -355,6 +355,7 @@ // get text QString &textOfLine = m_lines[line]->textReadWrite (); + int oldLength = textOfLine.size (); // check if valid column Q_ASSERT (range.start().column() >= 0); @@ -371,7 +372,7 @@ /** * notify the text history */ - m_buffer->history().removeText (range); + m_buffer->history().removeText (range, oldLength); /** * cursor and range handling below --- kate/buffer/katetexthistory.h.orig 2010-06-16 15:03:21.000000000 +0300 +++ kate/buffer/katetexthistory.h 2010-09-13 22:08:18.000000000 +0200 @@ -99,6 +99,14 @@ * @param moveOnInsert behavior of this cursor on insert of text at it's position */ void transformCursor (int &line, int &column, bool moveOnInsert) const; + + /** + * reverse transform cursor for this history entry + * @param line line number of the cursor to transform + * @param column column number of the cursor to transform + * @param moveOnInsert behavior of this cursor on insert of text at it's position + */ + void reverseTransformCursor (int &line, int &column, bool moveOnInsert) const; /** * Types of entries, matching editing primitives of buffer and placeholder @@ -195,8 +203,9 @@ /** * Notify about remove text at given range. * @param range range of text to remove, must be on one line only. + * @param oldLineLength text length of the line before this remove */ - void removeText (const KTextEditor::Range &range); + void removeText (const KTextEditor::Range &range, int oldLineLength); /** * Generic function to add a entry to the history. Is used by the above functions for the different editing primitives. --- kate/buffer/katetexthistory.cpp.orig 2010-06-16 15:03:21.000000000 +0300 +++ kate/buffer/katetexthistory.cpp 2010-09-13 22:08:06.000000000 +0200 @@ -94,7 +94,7 @@ addEntry (entry); } -void TextHistory::removeText (const KTextEditor::Range &range) +void TextHistory::removeText (const KTextEditor::Range &range, int oldLineLength) { // create and add new entry Entry entry; @@ -102,6 +102,7 @@ entry.line = range.start().line (); entry.column = range.start().column (); entry.length = range.end().column() - range.start().column(); + entry.oldLineLength = oldLineLength; addEntry (entry); } @@ -315,11 +316,131 @@ } } +void TextHistory::Entry::reverseTransformCursor (int &cursorLine, int &cursorColumn, bool moveOnInsert) const +{ + /** + * handle all history types + */ + switch (type) { + /** + * Wrap a line + */ + case WrapLine: + /** + * ignore this line + */ + if (cursorLine <= line) + return; + + /** + * next line is unwrapped + */ + if (cursorLine == line + 1) { + /** + * adjust column + */ + cursorColumn = cursorColumn + column; + } + + /** + * always decrement cursor line + */ + cursorLine -= 1; + return; + + /** + * Unwrap a line + */ + case UnwrapLine: + /** + * ignore lines before unwrapped one + */ + if (cursorLine < line - 1) + return; + + /** + * we unwrap this line, try to adjust cursor column if needed + */ + if (cursorLine == line - 1) { + /** + * skip cursors with to small columns + */ + if (cursorColumn <= oldLineLength) { + if (cursorColumn < oldLineLength || !moveOnInsert) + return; + } + + cursorColumn -= oldLineLength; + } + + /** + * increase cursor line + */ + cursorLine += 1; + return; + + /** + * Insert text + */ + case InsertText: + /** + * only interesting, if same line + */ + if (cursorLine != line) + return; + + // skip cursors with too small column + if (cursorColumn <= column) + return; + + // patch column of cursor + if (cursorColumn - length < column) + cursorColumn = column; + else + cursorColumn -= length; + + return; + + /** + * Remove text + */ + case RemoveText: + /** + * only interesting, if same line + */ + if (cursorLine != line) + return; + + // skip cursors with too small column + if (cursorColumn <= column) + if (cursorColumn < column || !moveOnInsert) + return; + + // patch column of cursor + if (cursorColumn <= oldLineLength) + cursorColumn += length; + + // special handling if cursor behind the real line, e.g. non-wrapping cursor in block selection mode + else if (cursorColumn < oldLineLength + length) + cursorColumn = oldLineLength + length; + return; + + /** + * nothing + */ + default: + return; + } +} + void TextHistory::transformCursor (int& line, int& column, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision) { /** - * -1 special meaning for toRevision + * -1 special meaning for from/toRevision */ + if (fromRevision == -1) + fromRevision = revision (); + if (toRevision == -1) toRevision = revision (); @@ -333,7 +454,7 @@ * some invariants must hold */ Q_ASSERT (!m_historyEntries.empty ()); - Q_ASSERT (fromRevision < toRevision); + Q_ASSERT (fromRevision != toRevision); Q_ASSERT (fromRevision >= m_firstHistoryEntryRevision); Q_ASSERT (fromRevision < (m_firstHistoryEntryRevision + m_historyEntries.size())); Q_ASSERT (toRevision >= m_firstHistoryEntryRevision); @@ -343,9 +464,20 @@ * transform cursor */ bool moveOnInsert = insertBehavior == KTextEditor::MovingCursor::MoveOnInsert; - for (int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) { - const Entry &entry = m_historyEntries[rev]; - entry.transformCursor (line, column, moveOnInsert); + + /** + * forward or reverse transform? + */ + if (toRevision > fromRevision) { + for (int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) { + const Entry &entry = m_historyEntries[rev]; + entry.transformCursor (line, column, moveOnInsert); + } + } else { + for (int rev = fromRevision - m_firstHistoryEntryRevision; rev >= (toRevision - m_firstHistoryEntryRevision + 1); --rev) { + const Entry &entry = m_historyEntries[rev]; + entry.reverseTransformCursor (line, column, moveOnInsert); + } } } @@ -361,8 +493,11 @@ } /** - * -1 special meaning for toRevision + * -1 special meaning for from/toRevision */ + if (fromRevision == -1) + fromRevision = revision (); + if (toRevision == -1) toRevision = revision (); @@ -376,40 +511,68 @@ * some invariants must hold */ Q_ASSERT (!m_historyEntries.empty ()); - Q_ASSERT (fromRevision < toRevision); + Q_ASSERT (fromRevision != toRevision); Q_ASSERT (fromRevision >= m_firstHistoryEntryRevision); Q_ASSERT (fromRevision < (m_firstHistoryEntryRevision + m_historyEntries.size())); Q_ASSERT (toRevision >= m_firstHistoryEntryRevision); Q_ASSERT (toRevision < (m_firstHistoryEntryRevision + m_historyEntries.size())); - + /** * transform cursors */ - + // first: copy cursors, without range association int startLine = range.start().line(), startColumn = range.start().column(), endLine = range.end().line(), endColumn = range.end().column(); bool moveOnInsertStart = !(insertBehaviors & KTextEditor::MovingRange::ExpandLeft); bool moveOnInsertEnd = (insertBehaviors & KTextEditor::MovingRange::ExpandRight); - for (int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) { - const Entry &entry = m_historyEntries[rev]; - - entry.transformCursor (startLine, startColumn, moveOnInsertStart); - - entry.transformCursor (endLine, endColumn, moveOnInsertEnd); + + /** + * forward or reverse transform? + */ + if (toRevision > fromRevision) { + for (int rev = fromRevision - m_firstHistoryEntryRevision + 1; rev <= (toRevision - m_firstHistoryEntryRevision); ++rev) { + const Entry &entry = m_historyEntries[rev]; + + entry.transformCursor (startLine, startColumn, moveOnInsertStart); + + entry.transformCursor (endLine, endColumn, moveOnInsertEnd); - // got empty? - if(endLine < startLine || (endLine == startLine && endColumn <= startColumn)) - { - if (invalidateIfEmpty) { - range = KTextEditor::Range::invalid(); - return; - } - else{ - // else normalize them - endLine = startLine; - endColumn = startColumn; - } + // got empty? + if(endLine < startLine || (endLine == startLine && endColumn <= startColumn)) + { + if (invalidateIfEmpty) { + range = KTextEditor::Range::invalid(); + return; + } + else{ + // else normalize them + endLine = startLine; + endColumn = startColumn; + } + } + } + } else { + for (int rev = fromRevision - m_firstHistoryEntryRevision ; rev >= (toRevision - m_firstHistoryEntryRevision + 1); --rev) { + const Entry &entry = m_historyEntries[rev]; + + entry.reverseTransformCursor (startLine, startColumn, moveOnInsertStart); + + entry.reverseTransformCursor (endLine, endColumn, moveOnInsertEnd); + + // got empty? + if(endLine < startLine || (endLine == startLine && endColumn <= startColumn)) + { + if (invalidateIfEmpty) { + range = KTextEditor::Range::invalid(); + return; + } + else{ + // else normalize them + endLine = startLine; + endColumn = startColumn; + } + } } }