src/gui/text/qtextdocument_p.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    61 #define PMDEBUG if(0) qDebug
    61 #define PMDEBUG if(0) qDebug
    62 
    62 
    63 // The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
    63 // The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
    64 #if !defined(Q_CC_DIAB)
    64 #if !defined(Q_CC_DIAB)
    65 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
    65 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
    66           QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }
    66           QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, a5, a6, { a7 }, a8 }
    67 #else
    67 #else
    68 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
    68 #  define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
    69           QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
    69           QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
    70 #endif
    70 #endif
    71 
    71 
   257         // also clear out the remaining root frame pointer
   257         // also clear out the remaining root frame pointer
   258         // (we're going to delete the object further down)
   258         // (we're going to delete the object further down)
   259         objects.clear();
   259         objects.clear();
   260 
   260 
   261         title.clear();
   261         title.clear();
   262         undoState = 0;
   262         clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
   263         truncateUndoStack();
       
   264         text = QString();
   263         text = QString();
   265         unreachableCharacterCount = 0;
   264         unreachableCharacterCount = 0;
   266         modifiedState = 0;
   265         modifiedState = 0;
   267         modified = false;
   266         modified = false;
   268         formats = QTextFormatCollection();
   267         formats = QTextFormatCollection();
   290     for (int i = 0; i < cursors.count(); ++i)
   289     for (int i = 0; i < cursors.count(); ++i)
   291         cursors.at(i)->priv = 0;
   290         cursors.at(i)->priv = 0;
   292     cursors.clear();
   291     cursors.clear();
   293     undoState = 0;
   292     undoState = 0;
   294     undoEnabled = true;
   293     undoEnabled = true;
   295     truncateUndoStack();
   294     clearUndoRedoStacks(QTextDocument::RedoStack);
   296 }
   295 }
   297 
   296 
   298 void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
   297 void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
   299 {
   298 {
   300     Q_Q(QTextDocument);
   299     Q_Q(QTextDocument);
   869         return -1;
   868         return -1;
   870 
   869 
   871     undoEnabled = false;
   870     undoEnabled = false;
   872     beginEditBlock();
   871     beginEditBlock();
   873     int editPos = -1;
   872     int editPos = -1;
       
   873     int editLength = -1;
   874     while (1) {
   874     while (1) {
   875         if (undo)
   875         if (undo)
   876             --undoState;
   876             --undoState;
   877         QTextUndoCommand &c = undoStack[undoState];
   877         QTextUndoCommand &c = undoStack[undoState];
   878         int resetBlockRevision = c.pos;
   878         int resetBlockRevision = c.pos;
   881         case QTextUndoCommand::Inserted:
   881         case QTextUndoCommand::Inserted:
   882             remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation);
   882             remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation);
   883             PMDEBUG("   erase: from %d, length %d", c.pos, c.length);
   883             PMDEBUG("   erase: from %d, length %d", c.pos, c.length);
   884             c.command = QTextUndoCommand::Removed;
   884             c.command = QTextUndoCommand::Removed;
   885             editPos = c.pos;
   885             editPos = c.pos;
       
   886             editLength = 0;
   886 	    break;
   887 	    break;
   887         case QTextUndoCommand::Removed:
   888         case QTextUndoCommand::Removed:
   888             PMDEBUG("   insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
   889             PMDEBUG("   insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
   889             insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
   890             insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
   890             c.command = QTextUndoCommand::Inserted;
   891             c.command = QTextUndoCommand::Inserted;
   891             editPos = c.pos + c.length;
   892             if (editPos != (int)c.pos)
       
   893                 editLength = 0;
       
   894             editPos = c.pos;
       
   895             editLength += c.length;
   892 	    break;
   896 	    break;
   893 	case QTextUndoCommand::BlockInserted:
   897 	case QTextUndoCommand::BlockInserted:
   894 	case QTextUndoCommand::BlockAdded:
   898 	case QTextUndoCommand::BlockAdded:
   895             remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation);
   899             remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation);
   896             PMDEBUG("   blockremove: from %d", c.pos);
   900             PMDEBUG("   blockremove: from %d", c.pos);
   897 	    if (c.command == QTextUndoCommand::BlockInserted)
   901 	    if (c.command == QTextUndoCommand::BlockInserted)
   898 		c.command = QTextUndoCommand::BlockRemoved;
   902 		c.command = QTextUndoCommand::BlockRemoved;
   899 	    else
   903 	    else
   900 		c.command = QTextUndoCommand::BlockDeleted;
   904 		c.command = QTextUndoCommand::BlockDeleted;
   901             editPos = c.pos;
   905             editPos = c.pos;
       
   906             editLength = 0;
   902 	    break;
   907 	    break;
   903 	case QTextUndoCommand::BlockRemoved:
   908 	case QTextUndoCommand::BlockRemoved:
   904 	case QTextUndoCommand::BlockDeleted:
   909 	case QTextUndoCommand::BlockDeleted:
   905             PMDEBUG("   blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
   910             PMDEBUG("   blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
   906             insert_block(c.pos, c.strPos, c.format, c.blockFormat, (QTextUndoCommand::Operation)c.operation, c.command);
   911             insert_block(c.pos, c.strPos, c.format, c.blockFormat, (QTextUndoCommand::Operation)c.operation, c.command);
   907             resetBlockRevision += 1;
   912             resetBlockRevision += 1;
   908 	    if (c.command == QTextUndoCommand::BlockRemoved)
   913 	    if (c.command == QTextUndoCommand::BlockRemoved)
   909 		c.command = QTextUndoCommand::BlockInserted;
   914 		c.command = QTextUndoCommand::BlockInserted;
   910 	    else
   915 	    else
   911 		c.command = QTextUndoCommand::BlockAdded;
   916 		c.command = QTextUndoCommand::BlockAdded;
   912             editPos = c.pos + 1;
   917             if (editPos != (int)c.pos)
       
   918                 editLength = 0;
       
   919             editPos = c.pos;
       
   920             editLength += 1;
   913 	    break;
   921 	    break;
   914 	case QTextUndoCommand::CharFormatChanged: {
   922 	case QTextUndoCommand::CharFormatChanged: {
   915             resetBlockRevision = -1; // ## TODO
   923             resetBlockRevision = -1; // ## TODO
   916             PMDEBUG("   charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
   924             PMDEBUG("   charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
   917             FragmentIterator it = find(c.pos);
   925             FragmentIterator it = find(c.pos);
   918             Q_ASSERT(!it.atEnd());
   926             Q_ASSERT(!it.atEnd());
   919 
   927 
   920             int oldFormat = it.value()->format;
   928             int oldFormat = it.value()->format;
   921             setCharFormat(c.pos, c.length, formats.charFormat(c.format));
   929             setCharFormat(c.pos, c.length, formats.charFormat(c.format));
   922             c.format = oldFormat;
   930             c.format = oldFormat;
   923             editPos = c.pos + c.length;
   931             if (editPos != (int)c.pos)
       
   932                 editLength = 0;
       
   933             editPos = c.pos;
       
   934             editLength += c.length;
   924 	    break;
   935 	    break;
   925 	}
   936 	}
   926 	case QTextUndoCommand::BlockFormatChanged: {
   937 	case QTextUndoCommand::BlockFormatChanged: {
   927             resetBlockRevision = -1; // ## TODO
   938             resetBlockRevision = -1; // ## TODO
   928             PMDEBUG("   blockformat: format %d pos %d", c.format, c.pos);
   939             PMDEBUG("   blockformat: format %d pos %d", c.format, c.pos);
   986                 );
   997                 );
   987         if (!inBlock)
   998         if (!inBlock)
   988             break;
   999             break;
   989     }
  1000     }
   990     undoEnabled = true;
  1001     undoEnabled = true;
   991     if (editPos < 0 && docChangeFrom >= 0) {
  1002 
   992         editPos = qMin(docChangeFrom + docChangeLength, length() - 1);
  1003     int newCursorPos = -1;
   993     }
  1004 
       
  1005     if (editPos >=0)
       
  1006         newCursorPos = editPos + editLength;
       
  1007     else if (docChangeFrom >= 0)
       
  1008         newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1);
       
  1009 
   994     endEditBlock();
  1010     endEditBlock();
   995     emitUndoAvailable(isUndoAvailable());
  1011     emitUndoAvailable(isUndoAvailable());
   996     emitRedoAvailable(isRedoAvailable());
  1012     emitRedoAvailable(isRedoAvailable());
   997     return editPos;
  1013 
       
  1014     return newCursorPos;
   998 }
  1015 }
   999 
  1016 
  1000 /*!
  1017 /*!
  1001     Appends a custom undo \a item to the undo stack.
  1018     Appends a custom undo \a item to the undo stack.
  1002 */
  1019 */
  1025 {
  1042 {
  1026     PMDEBUG("appendUndoItem, command=%d enabled=%d", c.command, undoEnabled);
  1043     PMDEBUG("appendUndoItem, command=%d enabled=%d", c.command, undoEnabled);
  1027     if (!undoEnabled)
  1044     if (!undoEnabled)
  1028         return;
  1045         return;
  1029     if (undoState < undoStack.size())
  1046     if (undoState < undoStack.size())
  1030         truncateUndoStack();
  1047         clearUndoRedoStacks(QTextDocument::RedoStack);
  1031 
  1048 
  1032     if (!undoStack.isEmpty() && modified) {
  1049     if (!undoStack.isEmpty() && modified) {
  1033         QTextUndoCommand &last = undoStack[undoState - 1];
  1050         QTextUndoCommand &last = undoStack[undoState - 1];
  1034 
  1051 
  1035         if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
  1052         if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
  1048 
  1065 
  1049     if (!c.block_part)
  1066     if (!c.block_part)
  1050         emit document()->undoCommandAdded();
  1067         emit document()->undoCommandAdded();
  1051 }
  1068 }
  1052 
  1069 
  1053 void QTextDocumentPrivate::truncateUndoStack()
  1070 void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
  1054 {
  1071                                                bool emitSignals)
  1055     if (undoState == undoStack.size())
  1072 {
  1056         return;
  1073     bool undoCommandsAvailable = undoState != 0;
  1057 
  1074     bool redoCommandsAvailable = undoState != undoStack.size();
  1058     for (int i = undoState; i < undoStack.size(); ++i) {
  1075     if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
  1059         QTextUndoCommand c = undoStack[i];
  1076         for (int i = 0; i < undoState; ++i) {
  1060         if (c.command & QTextUndoCommand::Removed) {
  1077             QTextUndoCommand c = undoStack[undoState];
  1061             // ########
  1078             if (c.command & QTextUndoCommand::Custom)
  1062 //             QTextFragment *f = c.fragment_list;
  1079                 delete c.custom;
  1063 //             while (f) {
  1080         }
  1064 //                 QTextFragment *n = f->right;
  1081         undoStack.remove(0, undoState);
  1065 //                 delete f;
  1082         undoStack.resize(undoStack.size() - undoState);
  1066 //                 f = n;
  1083         undoState = 0;
  1067 //             }
  1084         if (emitSignals)
  1068         } else if (c.command & QTextUndoCommand::Custom) {
  1085             emitUndoAvailable(false);
  1069             delete c.custom;
  1086     } else if (stacksToClear == QTextDocument::RedoStack
  1070         }
  1087                && redoCommandsAvailable) {
  1071     }
  1088         for (int i = undoState; i < undoStack.size(); ++i) {
  1072     undoStack.resize(undoState);
  1089             QTextUndoCommand c = undoStack[i];
       
  1090             if (c.command & QTextUndoCommand::Custom)
       
  1091                 delete c.custom;
       
  1092         }
       
  1093         undoStack.resize(undoState);
       
  1094         if (emitSignals)
       
  1095             emitRedoAvailable(false);
       
  1096     } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
       
  1097                && !undoStack.isEmpty()) {
       
  1098         for (int i = 0; i < undoStack.size(); ++i) {
       
  1099             QTextUndoCommand c = undoStack[i];
       
  1100             if (c.command & QTextUndoCommand::Custom)
       
  1101                 delete c.custom;
       
  1102         }
       
  1103         undoState = 0;
       
  1104         undoStack.resize(0);
       
  1105         if (emitSignals && undoCommandsAvailable)
       
  1106             emitUndoAvailable(false);
       
  1107         if (emitSignals && redoCommandsAvailable)
       
  1108             emitRedoAvailable(false);
       
  1109     }
  1073 }
  1110 }
  1074 
  1111 
  1075 void QTextDocumentPrivate::emitUndoAvailable(bool available)
  1112 void QTextDocumentPrivate::emitUndoAvailable(bool available)
  1076 {
  1113 {
  1077     if (available != wasUndoAvailable) {
  1114     if (available != wasUndoAvailable) {
  1095     if (enable && maximumBlockCount > 0)
  1132     if (enable && maximumBlockCount > 0)
  1096         return;
  1133         return;
  1097 
  1134 
  1098     if (!enable) {
  1135     if (!enable) {
  1099         undoState = 0;
  1136         undoState = 0;
  1100         truncateUndoStack();
  1137         clearUndoRedoStacks(QTextDocument::RedoStack);
  1101         emitUndoAvailable(false);
  1138         emitUndoAvailable(false);
  1102         emitRedoAvailable(false);
  1139         emitRedoAvailable(false);
  1103     }
  1140     }
  1104     modifiedState = modified ? -1 : undoState;
  1141     modifiedState = modified ? -1 : undoState;
  1105     undoEnabled = enable;
  1142     undoEnabled = enable;