Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/text/qtextdocument_p.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6161#define PMDEBUG if(0) qDebug
    6262
     63// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
     64#if !defined(Q_CC_DIAB)
     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 }
     67#else
     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
     70#endif
     71
    6372/*
    6473  Structure of a document:
     
    180189    docChangeLength(0),
    181190    framesDirty(true),
     191    rtFrame(0),
    182192    initialBlockCharFormatIndex(-1) // set correctly later in init()
    183193{
     
    186196
    187197    undoState = 0;
     198    revision = -1; // init() inserts a block, bringing it to 0
    188199
    189200    lout = 0;
     
    194205    undoEnabled = true;
    195206    inContentsChange = false;
     207
    196208    defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
    197209    defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
     
    208220void QTextDocumentPrivate::init()
    209221{
    210     rtFrame = 0;
    211222    framesDirty = false;
    212223
     
    231242
    232243    QList<QTextCursorPrivate *>oldCursors = cursors;
    233     cursors.clear();
    234     changedCursors.clear();
    235 
    236     QMap<int, QTextObject *>::Iterator objectIt = objects.begin();
    237     while (objectIt != objects.end()) {
    238         if (*objectIt != rtFrame) {
    239             delete *objectIt;
    240             objectIt = objects.erase(objectIt);
    241         } else {
    242             ++objectIt;
     244    QT_TRY{
     245        cursors.clear();
     246        changedCursors.clear();
     247
     248        QMap<int, QTextObject *>::Iterator objectIt = objects.begin();
     249        while (objectIt != objects.end()) {
     250            if (*objectIt != rtFrame) {
     251                delete *objectIt;
     252                objectIt = objects.erase(objectIt);
     253            } else {
     254                ++objectIt;
     255            }
    243256        }
    244     }
    245     // also clear out the remaining root frame pointer
    246     // (we're going to delete the object further down)
    247     objects.clear();
    248 
    249     title.clear();
    250     undoState = 0;
    251     truncateUndoStack();
    252     text = QString();
    253     unreachableCharacterCount = 0;
    254     modifiedState = 0;
    255     modified = false;
    256     formats = QTextFormatCollection();
    257     int len = fragments.length();
    258     fragments.clear();
    259     blocks.clear();
    260     cachedResources.clear();
    261     delete rtFrame;
    262     init();
    263     cursors = oldCursors;
    264     inContentsChange = true;
    265     q->contentsChange(0, len, 0);
    266     inContentsChange = false;
    267     if (lout)
    268         lout->documentChanged(0, len, 0);
     257        // also clear out the remaining root frame pointer
     258        // (we're going to delete the object further down)
     259        objects.clear();
     260
     261        title.clear();
     262        undoState = 0;
     263        truncateUndoStack();
     264        text = QString();
     265        unreachableCharacterCount = 0;
     266        modifiedState = 0;
     267        modified = false;
     268        formats = QTextFormatCollection();
     269        int len = fragments.length();
     270        fragments.clear();
     271        blocks.clear();
     272        cachedResources.clear();
     273        delete rtFrame;
     274        rtFrame = 0;
     275        init();
     276        cursors = oldCursors;
     277        inContentsChange = true;
     278        q->contentsChange(0, len, 0);
     279        inContentsChange = false;
     280        if (lout)
     281            lout->documentChanged(0, len, 0);
     282    } QT_CATCH(...) {
     283        cursors = oldCursors; // at least recover the cursors
     284        QT_RETHROW;
     285    }
    269286}
    270287
     
    405422    QTextBlockData *B = blocks.fragment(b);
    406423
    407     QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true,
    408                            op, charFormat, strPos, pos, { blockFormat },
    409                            B->revision };
     424    QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockInserted, (editBlock != 0),
     425                            op, charFormat, strPos, pos, blockFormat,
     426                            B->revision);
    410427
    411428    appendUndoItem(c);
     
    413430
    414431    // update revision numbers of the modified blocks.
    415     B->revision = (atBlockEnd && !atBlockStart)? oldRevision : undoState;
     432    B->revision = (atBlockEnd && !atBlockStart)? oldRevision : revision;
    416433    b = blocks.next(b);
    417434    if (b) {
    418435        B = blocks.fragment(b);
    419         B->revision = atBlockStart ? oldRevision : undoState;
     436        B->revision = atBlockStart ? oldRevision : revision;
    420437    }
    421438
     
    440457    Q_ASSERT(formats.format(format).isCharFormat());
    441458
    442     beginEditBlock();
    443459    insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);
    444460    if (undoEnabled) {
     
    446462        QTextBlockData *B = blocks.fragment(b);
    447463
    448         QTextUndoCommand c = { QTextUndoCommand::Inserted, true,
    449                                QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength },
    450                                B->revision };
     464        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Inserted, (editBlock != 0),
     465                                QTextUndoCommand::MoveCursor, format, strPos, pos, strLength,
     466                                B->revision);
    451467        appendUndoItem(c);
    452         B->revision = undoState;
     468        B->revision = revision;
    453469        Q_ASSERT(undoState == undoStack.size());
    454470    }
    455     endEditBlock();
     471    finishEdit();
    456472}
    457473
     
    585601#endif
    586602
    587     beginEditBlock();
    588 
    589603    split(pos);
    590604    split(pos+length);
     
    606620
    607621        QTextFragmentData *X = fragments.fragment(x);
    608         QTextUndoCommand c = { QTextUndoCommand::Removed, true,
    609                                op, X->format, X->stringPosition, key, { X->size_array[0] },
    610                                blockRevision };
    611         QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true,
    612                                      op, X->format, X->stringPosition, dstKey, { X->size_array[0] },
    613                                      blockRevision };
     622        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Removed, (editBlock != 0),
     623                                op, X->format, X->stringPosition, key, X->size_array[0],
     624                                blockRevision);
     625        QT_INIT_TEXTUNDOCOMMAND(cInsert, QTextUndoCommand::Inserted, (editBlock != 0),
     626                                op, X->format, X->stringPosition, dstKey, X->size_array[0],
     627                                blockRevision);
    614628
    615629        if (key+1 != blocks.position(b)) {
     
    638652        appendUndoItem(c);
    639653        if (B)
    640             B->revision = undoState;
     654            B->revision = revision;
    641655        x = n;
    642656
     
    649663    Q_ASSERT(blocks.length() == fragments.length());
    650664
    651     endEditBlock();
     665    finishEdit();
    652666}
    653667
     
    723737        }
    724738
    725         QTextUndoCommand c = { QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
    726                                0, pos, { length }, 0 };
     739        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
     740                                0, pos, length, 0);
    727741        appendUndoItem(c);
    728742
     
    783797        block(it)->invalidate();
    784798
    785         QTextUndoCommand c = { QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
    786                                0, it.position(), { 1 }, 0 };
     799        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
     800                                0, it.position(), 1, 0);
    787801        appendUndoItem(c);
    788802
     
    857871    undoEnabled = false;
    858872    beginEditBlock();
     873    int editPos = -1;
    859874    while (1) {
    860875        if (undo)
     
    868883            PMDEBUG("   erase: from %d, length %d", c.pos, c.length);
    869884            c.command = QTextUndoCommand::Removed;
     885            editPos = c.pos;
    870886            break;
    871887        case QTextUndoCommand::Removed:
     
    873889            insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);
    874890            c.command = QTextUndoCommand::Inserted;
     891            editPos = c.pos + c.length;
    875892            break;
    876893        case QTextUndoCommand::BlockInserted:
     
    882899            else
    883900                c.command = QTextUndoCommand::BlockDeleted;
     901            editPos = c.pos;
    884902            break;
    885903        case QTextUndoCommand::BlockRemoved:
     
    892910            else
    893911                c.command = QTextUndoCommand::BlockAdded;
     912            editPos = c.pos + 1;
    894913            break;
    895914        case QTextUndoCommand::CharFormatChanged: {
     
    902921            setCharFormat(c.pos, c.length, formats.charFormat(c.format));
    903922            c.format = oldFormat;
     923            editPos = c.pos + c.length;
    904924            break;
    905925        }
     
    924944            }
    925945            documentChange(it.position(), it.length());
     946            editPos = -1;
    926947            break;
    927948        }
     
    933954            changeObjectFormat(object, c.format);
    934955            c.format = oldFormat;
     956            editPos = -1;
    935957            break;
    936958        }
     
    941963            else
    942964                c.custom->redo();
     965            editPos = -1;
    943966            break;
    944967        default:
     
    952975        }
    953976
    954         if (undo) {
    955             if (undoState == 0 || !undoStack[undoState-1].block)
    956                 break;
    957         } else {
     977        if (!undo)
    958978            ++undoState;
    959             if (undoState == undoStack.size() || !undoStack[undoState-1].block)
    960                 break;
    961         }
     979
     980        bool inBlock = (
     981                undoState > 0
     982                && undoState < undoStack.size()
     983                && undoStack[undoState].block_part
     984                && undoStack[undoState-1].block_part
     985                && !undoStack[undoState-1].block_end
     986                );
     987        if (!inBlock)
     988            break;
    962989    }
    963990    undoEnabled = true;
    964     int editPos = -1;
    965     if (docChangeFrom >= 0) {
     991    if (editPos < 0 && docChangeFrom >= 0) {
    966992        editPos = qMin(docChangeFrom + docChangeLength, length() - 1);
    967993    }
     
    9841010    QTextUndoCommand c;
    9851011    c.command = QTextUndoCommand::Custom;
    986     c.block = editBlock != 0;
     1012    c.block_part = editBlock != 0;
     1013    c.block_end = 0;
    9871014    c.operation = QTextUndoCommand::MoveCursor;
    9881015    c.format = 0;
     
    10051032    if (!undoStack.isEmpty() && modified) {
    10061033        QTextUndoCommand &last = undoStack[undoState - 1];
    1007         if (last.tryMerge(c))
    1008             return;
     1034
     1035        if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
     1036            || (!c.block_part && !last.block_part)) {  // two single undo items => can merge
     1037
     1038            if (last.tryMerge(c))
     1039                return;
     1040        }
    10091041    }
    10101042    if (modifiedState > undoState)
     
    10141046    emitUndoAvailable(true);
    10151047    emitRedoAvailable(false);
     1048
     1049    if (!c.block_part)
     1050        emit document()->undoCommandAdded();
    10161051}
    10171052
     
    10781113
    10791114    if (undoEnabled && undoState)
    1080         undoStack[undoState - 1].block = true;
     1115        undoStack[undoState - 1].block_end = false;
    10811116}
    10821117
    10831118void QTextDocumentPrivate::endEditBlock()
    10841119{
     1120    Q_ASSERT(editBlock > 0);
     1121    if (--editBlock)
     1122        return;
     1123
     1124    if (undoEnabled && undoState > 0) {
     1125        const bool wasBlocking = !undoStack[undoState - 1].block_end;
     1126        if (undoStack[undoState - 1].block_part) {
     1127            undoStack[undoState - 1].block_end = true;
     1128            if (wasBlocking)
     1129                emit document()->undoCommandAdded();
     1130        }
     1131    }
     1132
     1133    finishEdit();
     1134}
     1135
     1136void QTextDocumentPrivate::finishEdit()
     1137{
    10851138    Q_Q(QTextDocument);
    1086     if (--editBlock)
    1087         return;
    1088 
    1089     if (undoEnabled && undoState > 0) {
    1090         const bool wasBlocking = undoStack[undoState - 1].block;
    1091         undoStack[undoState - 1].block = false;
    1092         if (wasBlocking)
    1093             emit document()->undoCommandAdded();
    1094     }
     1139
     1140    if (editBlock)
     1141        return;
    10951142
    10961143    if (framesDirty)
     
    11561203    param from is the cursor position in the document
    11571204    param addedOrRemoved is the amount of characters added or removed.  A negative number means characters are removed.
     1205
     1206    The function stores information to be emitted when finishEdit() is called.
    11581207*/
    11591208void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op)
    11601209{
    1161     Q_Q(QTextDocument);
     1210    if (!editBlock)
     1211        ++revision;
     1212
    11621213    for (int i = 0; i < cursors.size(); ++i) {
    11631214        QTextCursorPrivate *curs = cursors.at(i);
    11641215        if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
    1165             if (editBlock) {
    1166                 if (!changedCursors.contains(curs))
    1167                     changedCursors.append(curs);
    1168             } else {
    1169                 emit q->cursorPositionChanged(QTextCursor(curs));
    1170             }
     1216            if (!changedCursors.contains(curs))
     1217                changedCursors.append(curs);
    11711218        }
    11721219    }
     
    11841231//         qDebug("adjustDocumentChanges:");
    11851232//         qDebug("    -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);
    1186         contentsChanged();
    11871233        return;
    11881234    }
     
    12091255//     qDebug("    -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);
    12101256
    1211     contentsChanged();
    12121257}
    12131258
     
    12801325        documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());
    12811326
    1282     QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex,
    1283                            0, 0, { obj->d_func()->objectIndex }, 0 };
     1327    QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::GroupFormatChange, (editBlock != 0), QTextUndoCommand::MoveCursor, oldFormatIndex,
     1328                            0, 0, obj->d_func()->objectIndex, 0);
    12841329    appendUndoItem(c);
    12851330
Note: See TracChangeset for help on using the changeset viewer.