src/gui/text/qtextdocument_p.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 33 3e2da88830cd
--- a/src/gui/text/qtextdocument_p.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/gui/text/qtextdocument_p.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -63,7 +63,7 @@
 // The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
 #if !defined(Q_CC_DIAB)
 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
-          QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }
+          QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, a5, a6, { a7 }, a8 }
 #else
 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
           QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
@@ -259,8 +259,7 @@
         objects.clear();
 
         title.clear();
-        undoState = 0;
-        truncateUndoStack();
+        clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
         text = QString();
         unreachableCharacterCount = 0;
         modifiedState = 0;
@@ -292,7 +291,7 @@
     cursors.clear();
     undoState = 0;
     undoEnabled = true;
-    truncateUndoStack();
+    clearUndoRedoStacks(QTextDocument::RedoStack);
 }
 
 void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
@@ -871,6 +870,7 @@
     undoEnabled = false;
     beginEditBlock();
     int editPos = -1;
+    int editLength = -1;
     while (1) {
         if (undo)
             --undoState;
@@ -883,12 +883,16 @@
             PMDEBUG("   erase: from %d, length %d", c.pos, c.length);
             c.command = QTextUndoCommand::Removed;
             editPos = c.pos;
+            editLength = 0;
 	    break;
         case QTextUndoCommand::Removed:
             PMDEBUG("   insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
             insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
             c.command = QTextUndoCommand::Inserted;
-            editPos = c.pos + c.length;
+            if (editPos != (int)c.pos)
+                editLength = 0;
+            editPos = c.pos;
+            editLength += c.length;
 	    break;
 	case QTextUndoCommand::BlockInserted:
 	case QTextUndoCommand::BlockAdded:
@@ -899,6 +903,7 @@
 	    else
 		c.command = QTextUndoCommand::BlockDeleted;
             editPos = c.pos;
+            editLength = 0;
 	    break;
 	case QTextUndoCommand::BlockRemoved:
 	case QTextUndoCommand::BlockDeleted:
@@ -909,7 +914,10 @@
 		c.command = QTextUndoCommand::BlockInserted;
 	    else
 		c.command = QTextUndoCommand::BlockAdded;
-            editPos = c.pos + 1;
+            if (editPos != (int)c.pos)
+                editLength = 0;
+            editPos = c.pos;
+            editLength += 1;
 	    break;
 	case QTextUndoCommand::CharFormatChanged: {
             resetBlockRevision = -1; // ## TODO
@@ -920,7 +928,10 @@
             int oldFormat = it.value()->format;
             setCharFormat(c.pos, c.length, formats.charFormat(c.format));
             c.format = oldFormat;
-            editPos = c.pos + c.length;
+            if (editPos != (int)c.pos)
+                editLength = 0;
+            editPos = c.pos;
+            editLength += c.length;
 	    break;
 	}
 	case QTextUndoCommand::BlockFormatChanged: {
@@ -988,13 +999,19 @@
             break;
     }
     undoEnabled = true;
-    if (editPos < 0 && docChangeFrom >= 0) {
-        editPos = qMin(docChangeFrom + docChangeLength, length() - 1);
-    }
+
+    int newCursorPos = -1;
+
+    if (editPos >=0)
+        newCursorPos = editPos + editLength;
+    else if (docChangeFrom >= 0)
+        newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1);
+
     endEditBlock();
     emitUndoAvailable(isUndoAvailable());
     emitRedoAvailable(isRedoAvailable());
-    return editPos;
+
+    return newCursorPos;
 }
 
 /*!
@@ -1027,7 +1044,7 @@
     if (!undoEnabled)
         return;
     if (undoState < undoStack.size())
-        truncateUndoStack();
+        clearUndoRedoStacks(QTextDocument::RedoStack);
 
     if (!undoStack.isEmpty() && modified) {
         QTextUndoCommand &last = undoStack[undoState - 1];
@@ -1050,26 +1067,46 @@
         emit document()->undoCommandAdded();
 }
 
-void QTextDocumentPrivate::truncateUndoStack()
+void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
+                                               bool emitSignals)
 {
-    if (undoState == undoStack.size())
-        return;
-
-    for (int i = undoState; i < undoStack.size(); ++i) {
-        QTextUndoCommand c = undoStack[i];
-        if (c.command & QTextUndoCommand::Removed) {
-            // ########
-//             QTextFragment *f = c.fragment_list;
-//             while (f) {
-//                 QTextFragment *n = f->right;
-//                 delete f;
-//                 f = n;
-//             }
-        } else if (c.command & QTextUndoCommand::Custom) {
-            delete c.custom;
+    bool undoCommandsAvailable = undoState != 0;
+    bool redoCommandsAvailable = undoState != undoStack.size();
+    if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
+        for (int i = 0; i < undoState; ++i) {
+            QTextUndoCommand c = undoStack[undoState];
+            if (c.command & QTextUndoCommand::Custom)
+                delete c.custom;
         }
+        undoStack.remove(0, undoState);
+        undoStack.resize(undoStack.size() - undoState);
+        undoState = 0;
+        if (emitSignals)
+            emitUndoAvailable(false);
+    } else if (stacksToClear == QTextDocument::RedoStack
+               && redoCommandsAvailable) {
+        for (int i = undoState; i < undoStack.size(); ++i) {
+            QTextUndoCommand c = undoStack[i];
+            if (c.command & QTextUndoCommand::Custom)
+                delete c.custom;
+        }
+        undoStack.resize(undoState);
+        if (emitSignals)
+            emitRedoAvailable(false);
+    } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
+               && !undoStack.isEmpty()) {
+        for (int i = 0; i < undoStack.size(); ++i) {
+            QTextUndoCommand c = undoStack[i];
+            if (c.command & QTextUndoCommand::Custom)
+                delete c.custom;
+        }
+        undoState = 0;
+        undoStack.resize(0);
+        if (emitSignals && undoCommandsAvailable)
+            emitUndoAvailable(false);
+        if (emitSignals && redoCommandsAvailable)
+            emitRedoAvailable(false);
     }
-    undoStack.resize(undoState);
 }
 
 void QTextDocumentPrivate::emitUndoAvailable(bool available)
@@ -1097,7 +1134,7 @@
 
     if (!enable) {
         undoState = 0;
-        truncateUndoStack();
+        clearUndoRedoStacks(QTextDocument::RedoStack);
         emitUndoAvailable(false);
         emitRedoAvailable(false);
     }