/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <private/qtools_p.h>
#include <qdebug.h>

#include "qtextdocument_p.h"
#include "qtextdocument.h"
#include <qtextformat.h>
#include "qtextformat_p.h"
#include "qtextobject_p.h"
#include "qtextcursor.h"
#include "qtextimagehandler_p.h"
#include "qtextcursor_p.h"
#include "qtextdocumentlayout_p.h"
#include "qtexttable.h"
#include "qtextengine_p.h"

#include <stdlib.h>

QT_BEGIN_NAMESPACE

#define PMDEBUG if(0) qDebug

// 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, 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
#endif

/*
  Structure of a document:

  DOCUMENT :== FRAME_CONTENTS
  FRAME :== START_OF_FRAME  FRAME_CONTENTS END_OF_FRAME
  FRAME_CONTENTS = LIST_OF_BLOCKS ((FRAME | TABLE) LIST_OF_BLOCKS)*
  TABLE :== (START_OF_FRAME TABLE_CELL)+ END_OF_FRAME
  TABLE_CELL = FRAME_CONTENTS
  LIST_OF_BLOCKS :== (BLOCK END_OF_PARA)* BLOCK
  BLOCK :== (FRAGMENT)*
  FRAGMENT :== String of characters

  END_OF_PARA :== 0x2029 # Paragraph separator in Unicode
  START_OF_FRAME :== 0xfdd0
  END_OF_FRAME := 0xfdd1

  Note also that LIST_OF_BLOCKS can be empty. Nevertheless, there is
  at least one valid cursor position there where you could start
  typing. The block format is in this case determined by the last
  END_OF_PARA/START_OF_FRAME/END_OF_FRAME (see below).

  Lists are not in here, as they are treated specially. A list is just
  a collection of (not necessarily connected) blocks, that share the
  same objectIndex() in the format that refers to the list format and
  object.

  The above does not clearly note where formats are. Here's
  how it looks currently:

  FRAGMENT: one charFormat associated

  END_OF_PARA: one charFormat, and a blockFormat for the _next_ block.

  START_OF_FRAME: one char format, and a blockFormat (for the next
  block). The format associated with the objectIndex() of the
  charFormat decides whether this is a frame or table and its
  properties

  END_OF_FRAME: one charFormat and a blockFormat (for the next
  block). The object() of the charFormat is the same as for the
  corresponding START_OF_BLOCK.


  The document is independent of the layout with certain restrictions:

  * Cursor movement (esp. up and down) depend on the layout.
  * You cannot have more than one layout, as the layout data of QTextObjects
    is stored in the text object itself.

*/

void QTextBlockData::invalidate() const
{
    if (layout)
        layout->engine()->invalidate();
}

static bool isValidBlockSeparator(const QChar &ch)
{
    return ch == QChar::ParagraphSeparator
        || ch == QTextBeginningOfFrame
        || ch == QTextEndOfFrame;
}

#ifndef QT_NO_DEBUG
static bool noBlockInString(const QString &str)
{
    return !str.contains(QChar::ParagraphSeparator)
        && !str.contains(QTextBeginningOfFrame)
        && !str.contains(QTextEndOfFrame);
}
#endif

bool QTextUndoCommand::tryMerge(const QTextUndoCommand &other)
{
    if (command != other.command)
        return false;

    if (command == Inserted
        && (pos + length == other.pos)
        && (strPos + length == other.strPos)
        && format == other.format) {

        length += other.length;
        return true;
    }

    // removal to the 'right' using 'Delete' key
    if (command == Removed
        && pos == other.pos
        && (strPos + length == other.strPos)
        && format == other.format) {

        length += other.length;
        return true;
    }

    // removal to the 'left' using 'Backspace'
    if (command == Removed
        && (other.pos + other.length == pos)
        && (other.strPos + other.length == strPos)
        && (format == other.format)) {

        int l = length;
        (*this) = other;

        length += l;
        return true;
    }

    return false;
}

QTextDocumentPrivate::QTextDocumentPrivate()
    : wasUndoAvailable(false),
    wasRedoAvailable(false),
    docChangeOldLength(0),
    docChangeLength(0),
    framesDirty(true),
    rtFrame(0),
    initialBlockCharFormatIndex(-1) // set correctly later in init()
{
    editBlock = 0;
    editBlockCursorPosition = -1;
    docChangeFrom = -1;

    undoState = 0;
    revision = -1; // init() inserts a block, bringing it to 0

    lout = 0;

    modified = false;
    modifiedState = 0;

    undoEnabled = true;
    inContentsChange = false;
    blockCursorAdjustment = false;

    defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
    defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

    indentWidth = 40;
    documentMargin = 4;

    maximumBlockCount = 0;
    needsEnsureMaximumBlockCount = false;
    unreachableCharacterCount = 0;
    lastBlockCount = 0;
}

void QTextDocumentPrivate::init()
{
    framesDirty = false;

    bool undoState = undoEnabled;
    undoEnabled = false;
    initialBlockCharFormatIndex = formats.indexForFormat(QTextCharFormat());
    insertBlock(0, formats.indexForFormat(QTextBlockFormat()), formats.indexForFormat(QTextCharFormat()));
    undoEnabled = undoState;
    modified = false;
    modifiedState = 0;
}

void QTextDocumentPrivate::clear()
{
    Q_Q(QTextDocument);

    foreach (QTextCursorPrivate *curs, cursors) {
        curs->setPosition(0);
        curs->currentCharFormat = -1;
        curs->anchor = 0;
        curs->adjusted_anchor = 0;
    }

    QList<QTextCursorPrivate *>oldCursors = cursors;
    QT_TRY{
        cursors.clear();

        QMap<int, QTextObject *>::Iterator objectIt = objects.begin();
        while (objectIt != objects.end()) {
            if (*objectIt != rtFrame) {
                delete *objectIt;
                objectIt = objects.erase(objectIt);
            } else {
                ++objectIt;
            }
        }
        // also clear out the remaining root frame pointer
        // (we're going to delete the object further down)
        objects.clear();

        title.clear();
        clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
        text = QString();
        unreachableCharacterCount = 0;
        modifiedState = 0;
        modified = false;
        formats = QTextFormatCollection();
        int len = fragments.length();
        fragments.clear();
        blocks.clear();
        cachedResources.clear();
        delete rtFrame;
        rtFrame = 0;
        init();
        cursors = oldCursors;
        inContentsChange = true;
        q->contentsChange(0, len, 0);
        inContentsChange = false;
        if (lout)
            lout->documentChanged(0, len, 0);
    } QT_CATCH(...) {
        cursors = oldCursors; // at least recover the cursors
        QT_RETHROW;
    }
}

QTextDocumentPrivate::~QTextDocumentPrivate()
{
    foreach (QTextCursorPrivate *curs, cursors)
        curs->priv = 0;
    cursors.clear();
    undoState = 0;
    undoEnabled = true;
    clearUndoRedoStacks(QTextDocument::RedoStack);
}

void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
{
    Q_Q(QTextDocument);
    if (lout == layout)
        return;
    const bool firstLayout = !lout;
    delete lout;
    lout = layout;

    if (!firstLayout)
        for (BlockMap::Iterator it = blocks.begin(); !it.atEnd(); ++it)
            it->free();

    emit q->documentLayoutChanged();
    inContentsChange = true;
    emit q->contentsChange(0, 0, length());
    inContentsChange = false;
    if (lout)
        lout->documentChanged(0, 0, length());
}


void QTextDocumentPrivate::insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op)
{
    // ##### optimize when only appending to the fragment!
    Q_ASSERT(noBlockInString(text.mid(strPos, length)));

    split(pos);
    uint x = fragments.insert_single(pos, length);
    QTextFragmentData *X = fragments.fragment(x);
    X->format = format;
    X->stringPosition = strPos;
    uint w = fragments.previous(x);
    if (w)
        unite(w);

    int b = blocks.findNode(pos);
    blocks.setSize(b, blocks.size(b)+length);

    Q_ASSERT(blocks.length() == fragments.length());

    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(format));
    if (frame) {
        frame->d_func()->fragmentAdded(text.at(strPos), x);
        framesDirty = true;
    }

    adjustDocumentChangesAndCursors(pos, length, op);
}

int QTextDocumentPrivate::insert_block(int pos, uint strPos, int format, int blockFormat, QTextUndoCommand::Operation op, int command)
{
    split(pos);
    uint x = fragments.insert_single(pos, 1);
    QTextFragmentData *X = fragments.fragment(x);
    X->format = format;
    X->stringPosition = strPos;
    // no need trying to unite, since paragraph separators are always in a fragment of their own

    Q_ASSERT(isValidBlockSeparator(text.at(strPos)));
    Q_ASSERT(blocks.length()+1 == fragments.length());

    int block_pos = pos;
    if (blocks.length() && command == QTextUndoCommand::BlockRemoved)
        ++block_pos;
    int size = 1;
    int n = blocks.findNode(block_pos);
    int key = n ? blocks.position(n) : blocks.length();

    Q_ASSERT(n || (!n && block_pos == blocks.length()));
    if (key != block_pos) {
        Q_ASSERT(key < block_pos);
        int oldSize = blocks.size(n);
        blocks.setSize(n, block_pos-key);
        size += oldSize - (block_pos-key);
    }
    int b = blocks.insert_single(block_pos, size);
    QTextBlockData *B = blocks.fragment(b);
    B->format = blockFormat;

    Q_ASSERT(blocks.length() == fragments.length());

    QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blockFormat));
    if (group)
        group->blockInserted(QTextBlock(this, b));

    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(formats.format(format)));
    if (frame) {
        frame->d_func()->fragmentAdded(text.at(strPos), x);
        framesDirty = true;
    }

    adjustDocumentChangesAndCursors(pos, 1, op);
    return x;
}

int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,
                                  int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)
{
    Q_ASSERT(formats.format(blockFormat).isBlockFormat());
    Q_ASSERT(formats.format(charFormat).isCharFormat());
    Q_ASSERT(pos >= 0 && (pos < fragments.length() || (pos == 0 && fragments.length() == 0)));
    Q_ASSERT(isValidBlockSeparator(blockSeparator));

    beginEditBlock();

    int strPos = text.length();
    text.append(blockSeparator);

    int ob = blocks.findNode(pos);
    bool atBlockEnd = true;
    bool atBlockStart = true;
    int oldRevision = 0;
    if (ob) {
        atBlockEnd = (pos - blocks.position(ob) == blocks.size(ob)-1);
        atBlockStart = ((int)blocks.position(ob) == pos);
        oldRevision = blocks.fragment(ob)->revision;
    }

    const int fragment = insert_block(pos, strPos, charFormat, blockFormat, op, QTextUndoCommand::BlockRemoved);

    Q_ASSERT(blocks.length() == fragments.length());

    int b = blocks.findNode(pos);
    QTextBlockData *B = blocks.fragment(b);

    QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockInserted, (editBlock != 0),
                            op, charFormat, strPos, pos, blockFormat,
                            B->revision);

    appendUndoItem(c);
    Q_ASSERT(undoState == undoStack.size());

    // update revision numbers of the modified blocks.
    B->revision = (atBlockEnd && !atBlockStart)? oldRevision : revision;
    b = blocks.next(b);
    if (b) {
        B = blocks.fragment(b);
        B->revision = atBlockStart ? oldRevision : revision;
    }

    if (formats.charFormat(charFormat).objectIndex() == -1)
        needsEnsureMaximumBlockCount = true;

    endEditBlock();
    return fragment;
}

int QTextDocumentPrivate::insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)
{
    return insertBlock(QChar::ParagraphSeparator, pos, blockFormat, charFormat, op);
}

void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format)
{
    if (strLength <= 0)
        return;

    Q_ASSERT(pos >= 0 && pos < fragments.length());
    Q_ASSERT(formats.format(format).isCharFormat());

    insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);
    if (undoEnabled) {
        int b = blocks.findNode(pos);
        QTextBlockData *B = blocks.fragment(b);

        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Inserted, (editBlock != 0),
                                QTextUndoCommand::MoveCursor, format, strPos, pos, strLength,
                                B->revision);
        appendUndoItem(c);
        B->revision = revision;
        Q_ASSERT(undoState == undoStack.size());
    }
    finishEdit();
}

void QTextDocumentPrivate::insert(int pos, const QString &str, int format)
{
    if (str.size() == 0)
        return;

    Q_ASSERT(noBlockInString(str));

    int strPos = text.length();
    text.append(str);
    insert(pos, strPos, str.length(), format);
}

int QTextDocumentPrivate::remove_string(int pos, uint length, QTextUndoCommand::Operation op)
{
    Q_ASSERT(pos >= 0);
    Q_ASSERT(blocks.length() == fragments.length());
    Q_ASSERT(blocks.length() >= pos+(int)length);

    int b = blocks.findNode(pos);
    uint x = fragments.findNode(pos);

    Q_ASSERT(blocks.size(b) > length);
    Q_ASSERT(x && fragments.position(x) == (uint)pos && fragments.size(x) == length);
    Q_ASSERT(noBlockInString(text.mid(fragments.fragment(x)->stringPosition, length)));

    blocks.setSize(b, blocks.size(b)-length);

    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format));
    if (frame) {
        frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x);
        framesDirty = true;
    }

    const int w = fragments.erase_single(x);

    if (!undoEnabled)
        unreachableCharacterCount += length;

    adjustDocumentChangesAndCursors(pos, -int(length), op);

    return w;
}

int QTextDocumentPrivate::remove_block(int pos, int *blockFormat, int command, QTextUndoCommand::Operation op)
{
    Q_ASSERT(pos >= 0);
    Q_ASSERT(blocks.length() == fragments.length());
    Q_ASSERT(blocks.length() > pos);

    int b = blocks.findNode(pos);
    uint x = fragments.findNode(pos);

    Q_ASSERT(x && (int)fragments.position(x) == pos);
    Q_ASSERT(fragments.size(x) == 1);
    Q_ASSERT(isValidBlockSeparator(text.at(fragments.fragment(x)->stringPosition)));
    Q_ASSERT(b);

    if (blocks.size(b) == 1 && command == QTextUndoCommand::BlockAdded) {
	Q_ASSERT((int)blocks.position(b) == pos);
//  	qDebug("removing empty block");
	// empty block remove the block itself
    } else {
	// non empty block, merge with next one into this block
//  	qDebug("merging block with next");
	int n = blocks.next(b);
	Q_ASSERT((int)blocks.position(n) == pos + 1);
	blocks.setSize(b, blocks.size(b) + blocks.size(n) - 1);
        blocks.fragment(b)->userState = blocks.fragment(n)->userState;
	b = n;
    }
    *blockFormat = blocks.fragment(b)->format;

    QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blocks.fragment(b)->format));
    if (group)
        group->blockRemoved(QTextBlock(this, b));

    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format));
    if (frame) {
        frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x);
        framesDirty = true;
    }

    blocks.erase_single(b);
    const int w = fragments.erase_single(x);

    adjustDocumentChangesAndCursors(pos, -1, op);

    return w;
}

#if !defined(QT_NO_DEBUG)
static bool isAncestorFrame(QTextFrame *possibleAncestor, QTextFrame *child)
{
    while (child) {
        if (child == possibleAncestor)
            return true;
        child = child->parentFrame();
    }
    return false;
}
#endif

void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::Operation op)
{
    Q_ASSERT(to <= fragments.length() && to <= pos);
    Q_ASSERT(pos >= 0 && pos+length <= fragments.length());
    Q_ASSERT(blocks.length() == fragments.length());

    if (pos == to)
        return;

    const bool needsInsert = to != -1;

#if !defined(QT_NO_DEBUG)
    const bool startAndEndInSameFrame = (frameAt(pos) == frameAt(pos + length - 1));

    const bool endIsEndOfChildFrame = (isAncestorFrame(frameAt(pos), frameAt(pos + length - 1))
                                       && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame);

    const bool startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent
               = (text.at(find(pos)->stringPosition) == QTextBeginningOfFrame
                  && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame
                  && frameAt(pos)->parentFrame() == frameAt(pos + length - 1)->parentFrame());

    const bool isFirstTableCell = (qobject_cast<QTextTable *>(frameAt(pos + length - 1))
                                  && frameAt(pos + length - 1)->parentFrame() == frameAt(pos));

    Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);
#endif

    split(pos);
    split(pos+length);

    uint dst = needsInsert ? fragments.findNode(to) : 0;
    uint dstKey = needsInsert ? fragments.position(dst) : 0;

    uint x = fragments.findNode(pos);
    uint end = fragments.findNode(pos+length);

    uint w = 0;
    while (x != end) {
        uint n = fragments.next(x);

        uint key = fragments.position(x);
        uint b = blocks.findNode(key+1);
        QTextBlockData *B = blocks.fragment(b);
        int blockRevision = B->revision;

        QTextFragmentData *X = fragments.fragment(x);
        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Removed, (editBlock != 0),
                                op, X->format, X->stringPosition, key, X->size_array[0],
                                blockRevision);
        QT_INIT_TEXTUNDOCOMMAND(cInsert, QTextUndoCommand::Inserted, (editBlock != 0),
                                op, X->format, X->stringPosition, dstKey, X->size_array[0],
                                blockRevision);

        if (key+1 != blocks.position(b)) {
//	    qDebug("remove_string from %d length %d", key, X->size_array[0]);
            Q_ASSERT(noBlockInString(text.mid(X->stringPosition, X->size_array[0])));
            w = remove_string(key, X->size_array[0], op);

            if (needsInsert) {
                insert_string(dstKey, X->stringPosition, X->size_array[0], X->format, op);
                dstKey += X->size_array[0];
            }
        } else {
//	    qDebug("remove_block at %d", key);
            Q_ASSERT(X->size_array[0] == 1 && isValidBlockSeparator(text.at(X->stringPosition)));
            b = blocks.previous(b);
            B = 0;
            c.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockDeleted : QTextUndoCommand::BlockRemoved;
            w = remove_block(key, &c.blockFormat, QTextUndoCommand::BlockAdded, op);

            if (needsInsert) {
                insert_block(dstKey++, X->stringPosition, X->format, c.blockFormat, op, QTextUndoCommand::BlockRemoved);
                cInsert.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockAdded : QTextUndoCommand::BlockInserted;
                cInsert.blockFormat = c.blockFormat;
            }
        }
        appendUndoItem(c);
        if (B)
            B->revision = revision;
        x = n;

        if (needsInsert)
            appendUndoItem(cInsert);
    }
    if (w)
        unite(w);

    Q_ASSERT(blocks.length() == fragments.length());

    if (!blockCursorAdjustment)
        finishEdit();
}

void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op)
{
    if (length == 0)
        return;
    blockCursorAdjustment = true;
    move(pos, -1, length, op);
    blockCursorAdjustment = false;
    foreach (QTextCursorPrivate *curs, cursors) {
        if (curs->adjustPosition(pos, -length, op) == QTextCursorPrivate::CursorMoved) {
            curs->changed = true;
        }
    }
    finishEdit();
}

void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode)
{
    beginEditBlock();

    Q_ASSERT(newFormat.isValid());

    int newFormatIdx = -1;
    if (mode == SetFormatAndPreserveObjectIndices) {
        QTextCharFormat cleanFormat = newFormat;
        cleanFormat.clearProperty(QTextFormat::ObjectIndex);
        newFormatIdx = formats.indexForFormat(cleanFormat);
    } else if (mode == SetFormat) {
        newFormatIdx = formats.indexForFormat(newFormat);
    }

    if (pos == -1) {
        if (mode == MergeFormat) {
            QTextFormat format = formats.format(initialBlockCharFormatIndex);
            format.merge(newFormat);
            initialBlockCharFormatIndex = formats.indexForFormat(format);
        } else if (mode == SetFormatAndPreserveObjectIndices
                   && formats.format(initialBlockCharFormatIndex).objectIndex() != -1) {
            QTextCharFormat f = newFormat;
            f.setObjectIndex(formats.format(initialBlockCharFormatIndex).objectIndex());
            initialBlockCharFormatIndex = formats.indexForFormat(f);
        } else {
            initialBlockCharFormatIndex = newFormatIdx;
        }

        ++pos;
        --length;
    }

    const int startPos = pos;
    const int endPos = pos + length;

    split(startPos);
    split(endPos);

    while (pos < endPos) {
        FragmentMap::Iterator it = fragments.find(pos);
        Q_ASSERT(!it.atEnd());

        QTextFragmentData *fragment = it.value();

        Q_ASSERT(formats.format(fragment->format).type() == QTextFormat::CharFormat);

        int offset = pos - it.position();
        int length = qMin(endPos - pos, int(fragment->size_array[0] - offset));
        int oldFormat = fragment->format;

        if (mode == MergeFormat) {
            QTextFormat format = formats.format(fragment->format);
            format.merge(newFormat);
            fragment->format = formats.indexForFormat(format);
        } else if (mode == SetFormatAndPreserveObjectIndices
                   && formats.format(oldFormat).objectIndex() != -1) {
            QTextCharFormat f = newFormat;
            f.setObjectIndex(formats.format(oldFormat).objectIndex());
            fragment->format = formats.indexForFormat(f);
        } else {
            fragment->format = newFormatIdx;
        }

        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
                                0, pos, length, 0);
        appendUndoItem(c);

        pos += length;
        Q_ASSERT(pos == (int)(it.position() + fragment->size_array[0]) || pos >= endPos);
    }

    int n = fragments.findNode(startPos - 1);
    if (n)
        unite(n);

    n = fragments.findNode(endPos);
    if (n)
        unite(n);

    QTextBlock blockIt = blocksFind(startPos);
    QTextBlock endIt = blocksFind(endPos);
    if (endIt.isValid())
        endIt = endIt.next();
    for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())
        QTextDocumentPrivate::block(blockIt)->invalidate();

    documentChange(startPos, length);

    endEditBlock();
}

void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlock &to,
				     const QTextBlockFormat &newFormat, FormatChangeMode mode)
{
    beginEditBlock();

    Q_ASSERT(mode != SetFormatAndPreserveObjectIndices); // only implemented for setCharFormat

    Q_ASSERT(newFormat.isValid());

    int newFormatIdx = -1;
    if (mode == SetFormat)
        newFormatIdx = formats.indexForFormat(newFormat);
    QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(newFormat));

    QTextBlock it = from;
    QTextBlock end = to;
    if (end.isValid())
	end = end.next();

    for (; it != end; it = it.next()) {
        int oldFormat = block(it)->format;
        QTextBlockFormat format = formats.blockFormat(oldFormat);
        QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(format));
        if (mode == MergeFormat) {
            format.merge(newFormat);
            newFormatIdx = formats.indexForFormat(format);
            group = qobject_cast<QTextBlockGroup *>(objectForFormat(format));
        }
        block(it)->format = newFormatIdx;

        block(it)->invalidate();

        QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,
                                0, it.position(), 1, 0);
        appendUndoItem(c);

        if (group != oldGroup) {
            if (oldGroup)
                oldGroup->blockRemoved(it);
            if (group)
                group->blockInserted(it);
        } else if (group) {
	    group->blockFormatChanged(it);
	}
    }

    documentChange(from.position(), to.position() + to.length() - from.position());

    endEditBlock();
}


bool QTextDocumentPrivate::split(int pos)
{
    uint x = fragments.findNode(pos);
    if (x) {
        int k = fragments.position(x);
//          qDebug("found fragment with key %d, size_left=%d, size=%d to split at %d",
//                k, (*it)->size_left[0], (*it)->size_array[0], pos);
        if (k != pos) {
            Q_ASSERT(k <= pos);
            // need to resize the first fragment and add a new one
            QTextFragmentData *X = fragments.fragment(x);
            int oldsize = X->size_array[0];
            fragments.setSize(x, pos-k);
            uint n = fragments.insert_single(pos, oldsize-(pos-k));
            X = fragments.fragment(x);
            QTextFragmentData *N = fragments.fragment(n);
            N->stringPosition = X->stringPosition + pos-k;
            N->format = X->format;
            return true;
        }
    }
    return false;
}

bool QTextDocumentPrivate::unite(uint f)
{
    uint n = fragments.next(f);
    if (!n)
        return false;

    QTextFragmentData *ff = fragments.fragment(f);
    QTextFragmentData *nf = fragments.fragment(n);

    if (nf->format == ff->format && (ff->stringPosition + (int)ff->size_array[0] == nf->stringPosition)) {
        if (isValidBlockSeparator(text.at(ff->stringPosition))
            || isValidBlockSeparator(text.at(nf->stringPosition)))
            return false;

        fragments.setSize(f, ff->size_array[0] + nf->size_array[0]);
        fragments.erase_single(n);
        return true;
    }
    return false;
}


int QTextDocumentPrivate::undoRedo(bool undo)
{
    PMDEBUG("%s, undoState=%d, undoStack size=%d", undo ? "undo:" : "redo:", undoState, undoStack.size());
    if (!undoEnabled || (undo && undoState == 0) || (!undo && undoState == undoStack.size()))
        return -1;

    undoEnabled = false;
    beginEditBlock();
    int editPos = -1;
    int editLength = -1;
    while (1) {
        if (undo)
            --undoState;
        QTextUndoCommand &c = undoStack[undoState];
        int resetBlockRevision = c.pos;

	switch(c.command) {
        case QTextUndoCommand::Inserted:
            remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation);
            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;
            if (editPos != (int)c.pos)
                editLength = 0;
            editPos = c.pos;
            editLength += c.length;
	    break;
	case QTextUndoCommand::BlockInserted:
	case QTextUndoCommand::BlockAdded:
            remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation);
            PMDEBUG("   blockremove: from %d", c.pos);
	    if (c.command == QTextUndoCommand::BlockInserted)
		c.command = QTextUndoCommand::BlockRemoved;
	    else
		c.command = QTextUndoCommand::BlockDeleted;
            editPos = c.pos;
            editLength = 0;
	    break;
	case QTextUndoCommand::BlockRemoved:
	case QTextUndoCommand::BlockDeleted:
            PMDEBUG("   blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
            insert_block(c.pos, c.strPos, c.format, c.blockFormat, (QTextUndoCommand::Operation)c.operation, c.command);
            resetBlockRevision += 1;
	    if (c.command == QTextUndoCommand::BlockRemoved)
		c.command = QTextUndoCommand::BlockInserted;
	    else
		c.command = QTextUndoCommand::BlockAdded;
            if (editPos != (int)c.pos)
                editLength = 0;
            editPos = c.pos;
            editLength += 1;
	    break;
	case QTextUndoCommand::CharFormatChanged: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
            FragmentIterator it = find(c.pos);
            Q_ASSERT(!it.atEnd());

            int oldFormat = it.value()->format;
            setCharFormat(c.pos, c.length, formats.charFormat(c.format));
            c.format = oldFormat;
            if (editPos != (int)c.pos)
                editLength = 0;
            editPos = c.pos;
            editLength += c.length;
	    break;
	}
	case QTextUndoCommand::BlockFormatChanged: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   blockformat: format %d pos %d", c.format, c.pos);
            QTextBlock it = blocksFind(c.pos);
            Q_ASSERT(it.isValid());

            int oldFormat = block(it)->format;
            block(it)->format = c.format;
            QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(oldFormat)));
            QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(c.format)));
            c.format = oldFormat;
            if (group != oldGroup) {
                if (oldGroup)
                    oldGroup->blockRemoved(it);
                if (group)
                    group->blockInserted(it);
            } else if (group) {
                group->blockFormatChanged(it);
            }
            documentChange(it.position(), it.length());
            editPos = -1;
	    break;
	}
	case QTextUndoCommand::GroupFormatChange: {
            resetBlockRevision = -1; // ## TODO
            PMDEBUG("   group format change");
            QTextObject *object = objectForIndex(c.objectIndex);
            int oldFormat = formats.objectFormatIndex(c.objectIndex);
            changeObjectFormat(object, c.format);
            c.format = oldFormat;
            editPos = -1;
	    break;
	}
        case QTextUndoCommand::CursorMoved:
            editPos = c.pos;
            editLength = 0;
            break;
	case QTextUndoCommand::Custom:
            resetBlockRevision = -1; // ## TODO
            if (undo)
                c.custom->undo();
            else
                c.custom->redo();
            editPos = -1;
	    break;
	default:
	    Q_ASSERT(false);
        }

        if (resetBlockRevision >= 0) {
            int b = blocks.findNode(resetBlockRevision);
            QTextBlockData *B = blocks.fragment(b);
            B->revision = c.revision;
        }

        if (!undo)
            ++undoState;

        bool inBlock = (
                undoState > 0
                && undoState < undoStack.size()
                && undoStack[undoState].block_part
                && undoStack[undoState-1].block_part
                && !undoStack[undoState-1].block_end
                );
        if (!inBlock)
            break;
    }
    undoEnabled = true;

    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 newCursorPos;
}

/*!
    Appends a custom undo \a item to the undo stack.
*/
void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item)
{
    if (!undoEnabled) {
        delete item;
        return;
    }

    QTextUndoCommand c;
    c.command = QTextUndoCommand::Custom;
    c.block_part = editBlock != 0;
    c.block_end = 0;
    c.operation = QTextUndoCommand::MoveCursor;
    c.format = 0;
    c.strPos = 0;
    c.pos = 0;
    c.blockFormat = 0;

    c.custom = item;
    appendUndoItem(c);
}

void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
{
    PMDEBUG("appendUndoItem, command=%d enabled=%d", c.command, undoEnabled);
    if (!undoEnabled)
        return;
    if (undoState < undoStack.size())
        clearUndoRedoStacks(QTextDocument::RedoStack);

    if (editBlock != 0 && editBlockCursorPosition >= 0) { // we had a beginEditBlock() with a cursor position
        if (c.pos != (quint32) editBlockCursorPosition) { // and that cursor position is different from the command
            // generate a CursorMoved undo item
            QT_INIT_TEXTUNDOCOMMAND(cc, QTextUndoCommand::CursorMoved, true, QTextUndoCommand::MoveCursor,
                                    0, 0, editBlockCursorPosition, 0, 0);
            undoStack.append(cc);
            undoState++;
            editBlockCursorPosition = -1;
        }
    }


    if (!undoStack.isEmpty() && modified) {
        QTextUndoCommand &last = undoStack[undoState - 1];

        if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
            || (!c.block_part && !last.block_part)) {  // two single undo items => can merge

            if (last.tryMerge(c))
                return;
        }
    }
    if (modifiedState > undoState)
        modifiedState = -1;
    undoStack.append(c);
    undoState++;
    emitUndoAvailable(true);
    emitRedoAvailable(false);

    if (!c.block_part)
        emit document()->undoCommandAdded();
}

void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
                                               bool emitSignals)
{
    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);
    }
}

void QTextDocumentPrivate::emitUndoAvailable(bool available)
{
    if (available != wasUndoAvailable) {
        Q_Q(QTextDocument);
        emit q->undoAvailable(available);
        wasUndoAvailable = available;
    }
}

void QTextDocumentPrivate::emitRedoAvailable(bool available)
{
    if (available != wasRedoAvailable) {
        Q_Q(QTextDocument);
        emit q->redoAvailable(available);
        wasRedoAvailable = available;
    }
}

void QTextDocumentPrivate::enableUndoRedo(bool enable)
{
    if (enable && maximumBlockCount > 0)
        return;

    if (!enable) {
        undoState = 0;
        clearUndoRedoStacks(QTextDocument::RedoStack);
        emitUndoAvailable(false);
        emitRedoAvailable(false);
    }
    modifiedState = modified ? -1 : undoState;
    undoEnabled = enable;
    if (!undoEnabled)
        compressPieceTable();
}

void QTextDocumentPrivate::joinPreviousEditBlock()
{
    beginEditBlock();

    if (undoEnabled && undoState)
        undoStack[undoState - 1].block_end = false;
}

void QTextDocumentPrivate::endEditBlock()
{
    Q_ASSERT(editBlock > 0);
    if (--editBlock)
        return;

    if (undoEnabled && undoState > 0) {
        const bool wasBlocking = !undoStack[undoState - 1].block_end;
        if (undoStack[undoState - 1].block_part) {
            undoStack[undoState - 1].block_end = true;
            if (wasBlocking)
                emit document()->undoCommandAdded();
        }
    }

    editBlockCursorPosition = -1;

    finishEdit();
}

void QTextDocumentPrivate::finishEdit()
{
    Q_Q(QTextDocument);

    if (editBlock)
        return;

    if (framesDirty)
        scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);

    if (lout && docChangeFrom >= 0) {
        if (!inContentsChange) {
            inContentsChange = true;
            emit q->contentsChange(docChangeFrom, docChangeOldLength, docChangeLength);
            inContentsChange = false;
        }
        lout->documentChanged(docChangeFrom, docChangeOldLength, docChangeLength);
    }

    docChangeFrom = -1;

    if (needsEnsureMaximumBlockCount) {
        needsEnsureMaximumBlockCount = false;
        if (ensureMaximumBlockCount()) {
            // if ensureMaximumBlockCount() returns true
            // it will have called endEditBlock() and
            // compressPieceTable() itself, so we return here
            // to prevent getting two contentsChanged emits
            return;
        }
    }

    QList<QTextCursor> changedCursors;
    foreach (QTextCursorPrivate *curs, cursors) {
        if (curs->changed) {
            curs->changed = false;
            changedCursors.append(QTextCursor(curs));
        }
    }
    foreach (const QTextCursor &cursor, changedCursors)
        emit q->cursorPositionChanged(cursor);

    contentsChanged();

    if (blocks.numNodes() != lastBlockCount) {
        lastBlockCount = blocks.numNodes();
        emit q->blockCountChanged(lastBlockCount);
    }

    if (!undoEnabled && unreachableCharacterCount)
        compressPieceTable();
}

void QTextDocumentPrivate::documentChange(int from, int length)
{
//     qDebug("QTextDocumentPrivate::documentChange: from=%d,length=%d", from, length);
    if (docChangeFrom < 0) {
        docChangeFrom = from;
        docChangeOldLength = length;
        docChangeLength = length;
        return;
    }
    int start = qMin(from, docChangeFrom);
    int end = qMax(from + length, docChangeFrom + docChangeLength);
    int diff = qMax(0, end - start - docChangeLength);
    docChangeFrom = start;
    docChangeOldLength += diff;
    docChangeLength += diff;
}

/*
    adjustDocumentChangesAndCursors is called whenever there is an insert or remove of characters.
    param from is the cursor position in the document
    param addedOrRemoved is the amount of characters added or removed.  A negative number means characters are removed.

    The function stores information to be emitted when finishEdit() is called.
*/
void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op)
{
    if (!editBlock)
        ++revision;

    if (blockCursorAdjustment)  {
        ; // postpone, will be called again from QTextDocumentPrivate::remove()
    } else {
        foreach (QTextCursorPrivate *curs, cursors) {
            if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
                curs->changed = true;
            }
        }
    }

//     qDebug("QTextDocumentPrivate::adjustDocumentChanges: from=%d,addedOrRemoved=%d", from, addedOrRemoved);
    if (docChangeFrom < 0) {
        docChangeFrom = from;
        if (addedOrRemoved > 0) {
            docChangeOldLength = 0;
            docChangeLength = addedOrRemoved;
        } else {
            docChangeOldLength = -addedOrRemoved;
            docChangeLength = 0;
        }
//         qDebug("adjustDocumentChanges:");
//         qDebug("    -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);
        return;
    }

    // have to merge the new change with the already existing one.
    int added = qMax(0, addedOrRemoved);
    int removed = qMax(0, -addedOrRemoved);

    int diff = 0;
    if(from + removed < docChangeFrom)
        diff = docChangeFrom - from - removed;
    else if(from > docChangeFrom + docChangeLength)
        diff = from - (docChangeFrom + docChangeLength);

    int overlap_start = qMax(from, docChangeFrom);
    int overlap_end = qMin(from + removed, docChangeFrom + docChangeLength);
    int removedInside = qMax(0, overlap_end - overlap_start);
    removed -= removedInside;

//     qDebug("adjustDocumentChanges: from=%d, addedOrRemoved=%d, diff=%d, removedInside=%d", from, addedOrRemoved, diff, removedInside);
    docChangeFrom = qMin(docChangeFrom, from);
    docChangeOldLength += removed + diff;
    docChangeLength += added - removedInside + diff;
//     qDebug("    -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);

}


QString QTextDocumentPrivate::plainText() const
{
    QString result;
    result.resize(length());
    const QChar *text_unicode = text.unicode();
    QChar *data = result.data();
    for (QTextDocumentPrivate::FragmentIterator it = begin(); it != end(); ++it) {
        const QTextFragmentData *f = *it;
        ::memcpy(data, text_unicode + f->stringPosition, f->size_array[0] * sizeof(QChar));
        data += f->size_array[0];
    }
    // remove trailing block separator
    result.chop(1);
    return result;
}

int QTextDocumentPrivate::blockCharFormatIndex(int node) const
{
    int pos = blocks.position(node);
    if (pos == 0)
        return initialBlockCharFormatIndex;

    return fragments.find(pos - 1)->format;
}

int QTextDocumentPrivate::nextCursorPosition(int position, QTextLayout::CursorMode mode) const
{
    if (position == length()-1)
        return position;

    QTextBlock it = blocksFind(position);
    int start = it.position();
    int end = start + it.length() - 1;
    if (position == end)
        return end + 1;

    return it.layout()->nextCursorPosition(position-start, mode) + start;
}

int QTextDocumentPrivate::previousCursorPosition(int position, QTextLayout::CursorMode mode) const
{
    if (position == 0)
        return position;

    QTextBlock it = blocksFind(position);
    int start = it.position();
    if (position == start)
        return start - 1;

    return it.layout()->previousCursorPosition(position-start, mode) + start;
}

void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
{
    beginEditBlock();
    int objectIndex = obj->objectIndex();
    int oldFormatIndex = formats.objectFormatIndex(objectIndex);
    formats.setObjectFormatIndex(objectIndex, format);

    QTextBlockGroup *b = qobject_cast<QTextBlockGroup *>(obj);
    if (b) {
        b->d_func()->markBlocksDirty();
    }
    QTextFrame *f = qobject_cast<QTextFrame *>(obj);
    if (f)
        documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());

    QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::GroupFormatChange, (editBlock != 0), QTextUndoCommand::MoveCursor, oldFormatIndex,
                            0, 0, obj->d_func()->objectIndex, 0);
    appendUndoItem(c);

    endEditBlock();
}

static QTextFrame *findChildFrame(QTextFrame *f, int pos)
{
    // ##### use binary search
    QList<QTextFrame *> children = f->childFrames();
    for (int i = 0; i < children.size(); ++i) {
        QTextFrame *c = children.at(i);
        if (pos >= c->firstPosition() && pos <= c->lastPosition())
            return c;
    }
    return 0;
}

QTextFrame *QTextDocumentPrivate::rootFrame() const
{
    if (!rtFrame) {
        QTextFrameFormat defaultRootFrameFormat;
        defaultRootFrameFormat.setMargin(documentMargin);
        rtFrame = qobject_cast<QTextFrame *>(const_cast<QTextDocumentPrivate *>(this)->createObject(defaultRootFrameFormat));
    }
    return rtFrame;
}

QTextFrame *QTextDocumentPrivate::frameAt(int pos) const
{
    QTextFrame *f = rootFrame();

    while (1) {
        QTextFrame *c = findChildFrame(f, pos);
        if (!c)
            return f;
        f = c;
    }
}

void QTextDocumentPrivate::clearFrame(QTextFrame *f)
{
    for (int i = 0; i < f->d_func()->childFrames.count(); ++i)
        clearFrame(f->d_func()->childFrames.at(i));
    f->d_func()->childFrames.clear();
    f->d_func()->parentFrame = 0;
}

void QTextDocumentPrivate::scan_frames(int pos, int charsRemoved, int charsAdded)
{
    // ###### optimize
    Q_UNUSED(pos);
    Q_UNUSED(charsRemoved);
    Q_UNUSED(charsAdded);

    QTextFrame *f = rootFrame();
    clearFrame(f);

    for (FragmentIterator it = begin(); it != end(); ++it) {
        // QTextFormat fmt = formats.format(it->format);
        QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(it->format));
        if (!frame)
            continue;

        Q_ASSERT(it.size() == 1);
        QChar ch = text.at(it->stringPosition);

        if (ch == QTextBeginningOfFrame) {
            if (f != frame) {
                // f == frame happens for tables
                Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0);
                frame->d_func()->parentFrame = f;
                f->d_func()->childFrames.append(frame);
                f = frame;
            }
        } else if (ch == QTextEndOfFrame) {
            Q_ASSERT(f == frame);
            Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0);
            f = frame->d_func()->parentFrame;
        } else if (ch == QChar::ObjectReplacementCharacter) {
            Q_ASSERT(f != frame);
            Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0);
            Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0);
            frame->d_func()->parentFrame = f;
            f->d_func()->childFrames.append(frame);
        } else {
            Q_ASSERT(false);
        }
    }
    Q_ASSERT(f == rtFrame);
    framesDirty = false;
}

void QTextDocumentPrivate::insert_frame(QTextFrame *f)
{
    int start = f->firstPosition();
    int end = f->lastPosition();
    QTextFrame *parent = frameAt(start-1);
    Q_ASSERT(parent == frameAt(end+1));

    if (start != end) {
        // iterator over the parent and move all children contained in my frame to myself
        for (int i = 0; i < parent->d_func()->childFrames.size(); ++i) {
            QTextFrame *c = parent->d_func()->childFrames.at(i);
            if (start < c->firstPosition() && end > c->lastPosition()) {
                parent->d_func()->childFrames.removeAt(i);
                f->d_func()->childFrames.append(c);
                c->d_func()->parentFrame = f;
            }
        }
    }
    // insert at the correct position
    int i = 0;
    for (; i < parent->d_func()->childFrames.size(); ++i) {
        QTextFrame *c = parent->d_func()->childFrames.at(i);
        if (c->firstPosition() > end)
            break;
    }
    parent->d_func()->childFrames.insert(i, f);
    f->d_func()->parentFrame = parent;
}

QTextFrame *QTextDocumentPrivate::insertFrame(int start, int end, const QTextFrameFormat &format)
{
    Q_ASSERT(start >= 0 && start < length());
    Q_ASSERT(end >= 0 && end < length());
    Q_ASSERT(start <= end || end == -1);

    if (start != end && frameAt(start) != frameAt(end))
        return 0;

    beginEditBlock();

    QTextFrame *frame = qobject_cast<QTextFrame *>(createObject(format));
    Q_ASSERT(frame);

    // #### using the default block and char format below might be wrong
    int idx = formats.indexForFormat(QTextBlockFormat());
    QTextCharFormat cfmt;
    cfmt.setObjectIndex(frame->objectIndex());
    int charIdx = formats.indexForFormat(cfmt);

    insertBlock(QTextBeginningOfFrame, start, idx, charIdx, QTextUndoCommand::MoveCursor);
    insertBlock(QTextEndOfFrame, ++end, idx, charIdx, QTextUndoCommand::KeepCursor);

    frame->d_func()->fragment_start = find(start).n;
    frame->d_func()->fragment_end = find(end).n;

    insert_frame(frame);

    endEditBlock();

    return frame;
}

void QTextDocumentPrivate::removeFrame(QTextFrame *frame)
{
    QTextFrame *parent = frame->d_func()->parentFrame;
    if (!parent)
        return;

    int start = frame->firstPosition();
    int end = frame->lastPosition();
    Q_ASSERT(end >= start);

    beginEditBlock();

    // remove already removes the frames from the tree
    remove(end, 1);
    remove(start-1, 1);

    endEditBlock();
}

QTextObject *QTextDocumentPrivate::objectForIndex(int objectIndex) const
{
    if (objectIndex < 0)
        return 0;

    QTextObject *object = objects.value(objectIndex, 0);
    if (!object) {
        QTextDocumentPrivate *that = const_cast<QTextDocumentPrivate *>(this);
        QTextFormat fmt = formats.objectFormat(objectIndex);
        object = that->createObject(fmt, objectIndex);
    }
    return object;
}

QTextObject *QTextDocumentPrivate::objectForFormat(int formatIndex) const
{
    int objectIndex = formats.format(formatIndex).objectIndex();
    return objectForIndex(objectIndex);
}

QTextObject *QTextDocumentPrivate::objectForFormat(const QTextFormat &f) const
{
    return objectForIndex(f.objectIndex());
}

QTextObject *QTextDocumentPrivate::createObject(const QTextFormat &f, int objectIndex)
{
    QTextObject *obj = document()->createObject(f);

    if (obj) {
        obj->d_func()->objectIndex = objectIndex == -1 ? formats.createObjectIndex(f) : objectIndex;
        objects[obj->d_func()->objectIndex] = obj;
    }

    return obj;
}

void QTextDocumentPrivate::deleteObject(QTextObject *object)
{
    const int objIdx = object->d_func()->objectIndex;
    objects.remove(objIdx);
    delete object;
}

void QTextDocumentPrivate::contentsChanged()
{
    Q_Q(QTextDocument);
    if (editBlock)
        return;

    bool m = undoEnabled ? (modifiedState != undoState) : true;
    if (modified != m) {
        modified = m;
        emit q->modificationChanged(modified);
    }

    emit q->contentsChanged();
}

void QTextDocumentPrivate::compressPieceTable()
{
    if (undoEnabled)
        return;

    const uint garbageCollectionThreshold = 96 * 1024; // bytes

    //qDebug() << "unreachable bytes:" << unreachableCharacterCount * sizeof(QChar) << " -- limit" << garbageCollectionThreshold << "text size =" << text.size() << "capacity:" << text.capacity();

    bool compressTable = unreachableCharacterCount * sizeof(QChar) > garbageCollectionThreshold
                         && text.size() >= text.capacity() * 0.9;
    if (!compressTable)
        return;

    QString newText;
    newText.resize(text.size());
    QChar *newTextPtr = newText.data();
    int newLen = 0;

    for (FragmentMap::Iterator it = fragments.begin(); !it.atEnd(); ++it) {
        memcpy(newTextPtr, text.constData() + it->stringPosition, it->size_array[0] * sizeof(QChar));
        it->stringPosition = newLen;
        newTextPtr += it->size_array[0];
        newLen += it->size_array[0];
    }

    newText.resize(newLen);
    newText.squeeze();
    //qDebug() << "removed" << text.size() - newText.size() << "characters";
    text = newText;
    unreachableCharacterCount = 0;
}

void QTextDocumentPrivate::setModified(bool m)
{
    Q_Q(QTextDocument);
    if (m == modified)
        return;

    modified = m;
    if (!modified)
        modifiedState = undoState;
    else
        modifiedState = -1;

    emit q->modificationChanged(modified);
}

bool QTextDocumentPrivate::ensureMaximumBlockCount()
{
    if (maximumBlockCount <= 0)
        return false;
    if (blocks.numNodes() <= maximumBlockCount)
        return false;

    beginEditBlock();

    const int blocksToRemove = blocks.numNodes() - maximumBlockCount;
    QTextCursor cursor(this, 0);
    cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, blocksToRemove);

    unreachableCharacterCount += cursor.selectionEnd() - cursor.selectionStart();

    // preserve the char format of the paragraph that is to become the new first one
    QTextCharFormat charFmt = cursor.blockCharFormat();
    cursor.removeSelectedText();
    cursor.setBlockCharFormat(charFmt);

    endEditBlock();

    compressPieceTable();

    return true;
}

/// This method is called from QTextTable when it is about to remove a table-cell to allow cursors to update their selection.
void QTextDocumentPrivate::aboutToRemoveCell(int from, int to)
{
    Q_ASSERT(from <= to);
    foreach (QTextCursorPrivate *curs, cursors)
        curs->aboutToRemoveCell(from, to);
}

QT_END_NAMESPACE
