From 29eff525295fd98697a6682cea648b14a83959cd Mon Sep 17 00:00:00 2001
From: hjk <qthjk@ovi.com>
Date: Tue, 27 Dec 2011 17:39:56 +0100
Subject: [PATCH] fakevim: rework undo/redo cursor positioning

Change-Id: I1daa788377295fb1446f31d9a74b9fd0df6920d1
Reviewed-by: hjk <qthjk@ovi.com>
---
 src/plugins/fakevim/fakevimhandler.cpp | 106 ++++++++++++++-----------
 1 file changed, 61 insertions(+), 45 deletions(-)

diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 0bd773c3042..33f2e25e46d 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -862,8 +862,6 @@ public:
         { return document()->characterAt(position()); }
     void beginEditBlock()
         { UNDO_DEBUG("BEGIN EDIT BLOCK"); cursor().beginEditBlock(); }
-    void beginEditBlock(int pos)
-        { setUndoPosition(pos); cursor().beginEditBlock(); }
     void endEditBlock()
         { UNDO_DEBUG("END EDIT BLOCK"); cursor().endEditBlock(); }
     void joinPreviousEditBlock()
@@ -982,7 +980,7 @@ public:
     // undo handling
     void undo();
     void redo();
-    void setUndoPosition(int pos);
+    void setUndoPosition();
     QMap<int, int> m_undoCursorPosition; // revision -> position
 
     // extra data for '.'
@@ -1433,7 +1431,6 @@ EventResult FakeVimHandler::Private::handleKey(const Input &input)
 
 EventResult FakeVimHandler::Private::handleKey2()
 {
-    setUndoPosition(position());
     if (m_mode == InsertMode) {
         EventResult result = EventUnhandled;
         foreach (const Input &in, g.pendingInput) {
@@ -1484,9 +1481,13 @@ void FakeVimHandler::Private::stopIncrementalFind()
     }
 }
 
-void FakeVimHandler::Private::setUndoPosition(int pos)
+void FakeVimHandler::Private::setUndoPosition()
 {
-    m_undoCursorPosition[document()->availableUndoSteps()] = pos;
+    int pos = qMin(position(), anchor());
+    if (m_visualMode == VisualLineMode)
+        pos = firstPositionInLine(lineForPosition(pos));
+    const int rev = document()->availableUndoSteps();
+    m_undoCursorPosition[rev] = pos;
 }
 
 void FakeVimHandler::Private::moveDown(int n)
@@ -1607,7 +1608,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
         if (m_movetype == MoveLineWise)
             insertAutomaticIndentation(true);
         endEditBlock();
-        setUndoPosition(position());
         enterInsertMode();
         m_submode = NoSubMode;
     } else if (m_submode == DeleteSubMode) {
@@ -1656,16 +1656,17 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
             handleStartOfLine();
         endEditBlock();
     } else if (m_submode == IndentSubMode) {
+        setUndoPosition();
         recordJump();
-        beginEditBlock();
         indentSelectedText();
-        endEditBlock();
         m_submode = NoSubMode;
     } else if (m_submode == ShiftRightSubMode) {
+        setUndoPosition();
         recordJump();
         shiftRegionRight(1);
         m_submode = NoSubMode;
     } else if (m_submode == ShiftLeftSubMode) {
+        setUndoPosition();
         recordJump();
         shiftRegionLeft(1);
         m_submode = NoSubMode;
@@ -1926,6 +1927,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
         m_rangemode = RangeLineMode;
     } else if (m_submode == ReplaceSubMode) {
         if (isVisualMode()) {
+            setUndoPosition();
             m_lastChangePosition = position();
             if (isVisualLineMode())
                 m_rangemode = RangeLineMode;
@@ -1940,6 +1942,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
             transformText(range, tr, input.asChar());
             setPosition(range.beginPos);
         } else if (count() <= rightDist()) {
+            setUndoPosition();
             m_lastChangePosition = position();
             setAnchor();
             moveRight(count());
@@ -1959,6 +1962,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
         m_submode = NoSubMode;
         finishMovement();
     } else if (m_submode == ChangeSubMode && input.is('c')) { // tested
+        setUndoPosition();
         m_lastChangePosition = position();
         moveToStartOfLine();
         setAnchor();
@@ -1969,6 +1973,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
         setDotCommand("%1cc", count());
         finishMovement();
     } else if (m_submode == DeleteSubMode && input.is('d')) { // tested
+        setUndoPosition();
         m_lastChangePosition = position();
         m_movetype = MoveLineWise;
         int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1);
@@ -2198,29 +2203,36 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
         replay(savedCommand, count());
         enterCommandMode();
         g.dotCommand = savedCommand;
-    } else if (input.is('<') && isNoVisualMode()) {
-        m_submode = ShiftLeftSubMode;
-    } else if (input.is('<') && isVisualMode()) {
-        shiftRegionLeft(1);
-        leaveVisualMode();
-    } else if (input.is('>') && isNoVisualMode()) {
-        m_submode = ShiftRightSubMode;
-    } else if (input.is('>') && isVisualMode()) {
-        shiftRegionRight(1);
-        leaveVisualMode();
-    } else if (input.is('=') && isNoVisualMode()) {
-        m_submode = IndentSubMode;
-    } else if (input.is('=') && isVisualMode()) {
-        beginEditBlock();
-        indentSelectedText();
-        endEditBlock();
-        leaveVisualMode();
+    } else if (input.is('<')) {
+        setUndoPosition();
+        if (isNoVisualMode()) {
+            m_submode = ShiftLeftSubMode;
+        } else {
+            shiftRegionLeft(1);
+            leaveVisualMode();
+        }
+    } else if (input.is('>')) {
+        setUndoPosition();
+        if (isNoVisualMode()) {
+            m_submode = ShiftRightSubMode;
+        } else {
+            shiftRegionRight(1);
+            leaveVisualMode();
+        }
+    } else if (input.is('=')) {
+        setUndoPosition();
+        if (isNoVisualMode()) {
+            m_submode = IndentSubMode;
+        } else {
+            indentSelectedText();
+            leaveVisualMode();
+        }
     } else if (input.is('%')) {
         moveToMatchingParanthesis();
         finishMovement();
     } else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) {
         leaveVisualMode();
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         enterInsertMode();
         m_lastInsertion.clear();
@@ -2228,7 +2240,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
             moveRight();
         updateMiniBuffer();
     } else if (input.is('A')) {
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         moveBehindEndOfLine();
         setAnchor();
@@ -2249,6 +2261,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
         setTargetColumn();
         finishMovement();
     } else if (input.is('c') && isNoVisualMode()) {
+        setUndoPosition();
         if (atEndOfLine())
             moveLeft();
         setAnchor();
@@ -2399,7 +2412,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
         finishMovement();
     } else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) {
         setDotCommand(QString(QLatin1Char('i'))); // setDotCommand("%1i", count());
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         enterInsertMode();
         updateMiniBuffer();
@@ -2416,6 +2429,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
     EventResult handled = EventHandled;
 
     if (input.is('I')) {
+        setUndoPosition();
         setDotCommand(QString(QLatin1Char('I'))); // setDotCommand("%1I", count());
         if (isVisualMode()) {
             int beginLine = lineForPosition(anchor());
@@ -2430,7 +2444,6 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
             m_gflag = false;
             //m_tc.clearSelection();
         }
-        setUndoPosition(position());
         breakEditBlock();
         enterInsertMode();
     } else if (input.isControl('i')) {
@@ -2530,10 +2543,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
         updateSelection();
     } else if (input.is('o')) {
         setDotCommand("%1o", count());
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         enterInsertMode();
-        beginEditBlock(position());
+        beginEditBlock();
         moveToFirstNonBlankOnLine();
         moveBehindEndOfLine();
         insertText(QString("\n"));
@@ -2541,10 +2554,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
         endEditBlock();
     } else if (input.is('O')) {
         setDotCommand("%1O", count());
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         enterInsertMode();
-        beginEditBlock(position());
+        beginEditBlock();
         moveToFirstNonBlankOnLine();
         moveToStartOfLine();
         insertText(QString("\n"));
@@ -2563,15 +2576,17 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
         setDotCommand("%1p", count());
         finishMovement();
     } else if (input.is('r')) {
+        setUndoPosition();
         m_submode = ReplaceSubMode;
     } else if (!isVisualMode() && input.is('R')) {
-        setUndoPosition(position());
+        setUndoPosition();
         breakEditBlock();
         enterReplaceMode();
         updateMiniBuffer();
     } else if (input.isControl('r')) {
         redo();
     } else if (input.is('s') && isVisualBlockMode()) {
+        setUndoPosition();
         Range range(position(), anchor(), RangeBlockMode);
         int beginLine = lineForPosition(anchor());
         int endLine = lineForPosition(position());
@@ -2580,10 +2595,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
         yankText(range, m_register);
         removeText(range);
         setDotCommand("%1s", count());
-        setUndoPosition(position());
         breakEditBlock();
         enterInsertMode();
     } else if (input.is('s')) {
+        setUndoPosition();
         leaveVisualMode();
         if (atEndOfLine())
             moveLeft();
@@ -2594,10 +2609,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
         setDotCommand("%1s", count());
         m_opcount.clear();
         m_mvcount.clear();
-        setUndoPosition(position());
         breakEditBlock();
         enterInsertMode();
     } else if (input.is('S')) {
+        setUndoPosition();
         beginEditBlock();
         if (!isVisualMode()) {
             const int line = cursorLine() + 1;
@@ -2606,7 +2621,6 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
             setAnchorAndPosition(anc, pos);
         }
         setDotCommand("%1S", count());
-        setUndoPosition(position());
         breakEditBlock();
         enterInsertMode();
         m_submode = ChangeSubMode;
@@ -3625,7 +3639,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
     if (endLine == -1)
         endLine = linesInDocument();
     //qDebug() << "LINES: " << beginLine << endLine;
-    QString prefix = cmd.args;
+    //QString prefix = cmd.args;
     const bool forced = cmd.hasBang;
     //const bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
     //const bool quitAll = quit && prefix.contains(QChar('a'));
@@ -3711,7 +3725,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
     proc.closeWriteChannel();
     proc.waitForFinished();
     QString result = QString::fromUtf8(proc.readAllStandardOutput());
-    beginEditBlock(targetPosition);
+    beginEditBlock();
     removeText(currentRange());
     insertText(result);
     setPosition(targetPosition);
@@ -4052,6 +4066,7 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine()
 
 void FakeVimHandler::Private::indentSelectedText(QChar typedChar)
 {
+    beginEditBlock();
     setTargetColumn();
     int beginLine = qMin(lineForPosition(position()), lineForPosition(anchor()));
     int endLine = qMax(lineForPosition(position()), lineForPosition(anchor()));
@@ -4063,6 +4078,7 @@ void FakeVimHandler::Private::indentSelectedText(QChar typedChar)
     handleStartOfLine();
     setTargetColumn();
     setDotCommand("%1==", endLine - beginLine + 1);
+    endEditBlock();
 }
 
 void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar)
@@ -4098,7 +4114,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat)
         targetPos = firstPositionInLine(beginLine);
 
     const int sw = config(ConfigShiftWidth).toInt();
-    beginEditBlock(targetPos);
+    beginEditBlock();
     for (int line = beginLine; line <= endLine; ++line) {
         QString data = lineContents(line);
         const Column col = indentation(data);
@@ -4127,7 +4143,7 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
     if (hasConfig(ConfigStartOfLine))
         targetPos = firstPositionInLine(beginLine);
 
-    beginEditBlock(targetPos);
+    beginEditBlock();
     for (int line = endLine; line >= beginLine; --line) {
         int pos = firstPositionInLine(line);
         const QString text = lineContents(line);
@@ -4479,7 +4495,7 @@ QString FakeVimHandler::Private::selectText(const Range &range) const
         int firstPos = firstPositionInLine(lineForPosition(range.beginPos));
         int lastLine = lineForPosition(range.endPos);
         bool endOfDoc = lastLine == document()->lastBlock().blockNumber() + 1;
-        int lastPos = endOfDoc ? lastPositionInDocument()  : firstPositionInLine(lastLine + 1);
+        int lastPos = endOfDoc ? lastPositionInDocument() : firstPositionInLine(lastLine + 1);
         tc.setPosition(firstPos, MoveAnchor);
         tc.setPosition(lastPos, KeepAnchor);
         return tc.selection().toPlainText() + QString((endOfDoc? "\n" : ""));
@@ -4539,7 +4555,7 @@ void FakeVimHandler::Private::transformText(const Range &range,
         }
         case RangeLineMode:
         case RangeLineModeExclusive: {
-            beginEditBlock(range.beginPos);
+            beginEditBlock();
             tc.setPosition(range.beginPos, MoveAnchor);
             tc.movePosition(StartOfLine, MoveAnchor);
             tc.setPosition(range.endPos, KeepAnchor);
@@ -4579,7 +4595,7 @@ void FakeVimHandler::Private::transformText(const Range &range,
             if (range.rangemode == RangeBlockAndTailMode)
                 endColumn = INT_MAX - 1;
             QTextBlock block = document()->findBlockByNumber(endLine - 1);
-            beginEditBlock(range.beginPos);
+            beginEditBlock();
             for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
                 int bCol = qMin(beginColumn, block.length() - 1);
                 int eCol = qMin(endColumn + 1, block.length() - 1);
-- 
GitLab