src/gui/text/qtextobject.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qtextobject.h"
       
    43 #include "qtextobject_p.h"
       
    44 #include "qtextdocument.h"
       
    45 #include "qtextformat_p.h"
       
    46 #include "qtextdocument_p.h"
       
    47 #include "qtextcursor.h"
       
    48 #include "qtextlist.h"
       
    49 #include "qabstracttextdocumentlayout.h"
       
    50 #include "qtextengine_p.h"
       
    51 #include "qdebug.h"
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 // ### DOC: We ought to explain the CONCEPT of objectIndexes if
       
    56 // relevant to the public API
       
    57 /*!
       
    58     \class QTextObject
       
    59     \reentrant
       
    60 
       
    61     \brief The QTextObject class is a base class for different kinds
       
    62     of objects that can group parts of a QTextDocument together.
       
    63 
       
    64     \ingroup richtext-processing
       
    65 
       
    66     The common grouping text objects are lists (QTextList), frames
       
    67     (QTextFrame), and tables (QTextTable). A text object has an
       
    68     associated format() and document().
       
    69 
       
    70     There are essentially two kinds of text objects: those that are used
       
    71     with blocks (block formats), and those that are used with characters
       
    72     (character formats). The first kind are derived from QTextBlockGroup,
       
    73     and the second kind from QTextFrame.
       
    74 
       
    75     You rarely need to use this class directly. When creating custom text
       
    76     objects, you will also need to reimplement QTextDocument::createObject()
       
    77     which acts as a factory method for creating text objects.
       
    78 
       
    79     \sa QTextDocument, {Text Object Example}
       
    80 */
       
    81 
       
    82 /*!
       
    83     \fn QTextObject::QTextObject(QTextDocument *document)
       
    84 
       
    85     Creates a new QTextObject for the given \a document.
       
    86 
       
    87     \warning This function should never be called directly, but only
       
    88     from QTextDocument::createObject().
       
    89 */
       
    90 QTextObject::QTextObject(QTextDocument *doc)
       
    91     : QObject(*new QTextObjectPrivate(doc), doc)
       
    92 {
       
    93 }
       
    94 
       
    95 /*!
       
    96   \fn QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *document)
       
    97 
       
    98   \internal
       
    99 */
       
   100 QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *doc)
       
   101     : QObject(p, doc)
       
   102 {
       
   103 }
       
   104 
       
   105 /*!
       
   106     Destroys the text object.
       
   107 
       
   108     \warning Text objects are owned by the document, so you should
       
   109     never destroy them yourself.
       
   110 */
       
   111 QTextObject::~QTextObject()
       
   112 {
       
   113 }
       
   114 
       
   115 /*!
       
   116     Returns the text object's format.
       
   117 
       
   118     \sa setFormat() document()
       
   119 */
       
   120 QTextFormat QTextObject::format() const
       
   121 {
       
   122     Q_D(const QTextObject);
       
   123     return d->pieceTable->formatCollection()->objectFormat(d->objectIndex);
       
   124 }
       
   125 
       
   126 /*!
       
   127     Returns the index of the object's format in the document's internal
       
   128     list of formats.
       
   129 
       
   130     \sa QTextDocument::allFormats()
       
   131 */
       
   132 int QTextObject::formatIndex() const
       
   133 {
       
   134     Q_D(const QTextObject);
       
   135     return d->pieceTable->formatCollection()->objectFormatIndex(d->objectIndex);
       
   136 }
       
   137 
       
   138 
       
   139 /*!
       
   140     Sets the text object's \a format.
       
   141 
       
   142     \sa format()
       
   143 */
       
   144 void QTextObject::setFormat(const QTextFormat &format)
       
   145 {
       
   146     Q_D(QTextObject);
       
   147     int idx = d->pieceTable->formatCollection()->indexForFormat(format);
       
   148     d->pieceTable->changeObjectFormat(this, idx);
       
   149 }
       
   150 
       
   151 /*!
       
   152     Returns the object index of this object. This can be used together with
       
   153     QTextFormat::setObjectIndex().
       
   154 */
       
   155 int QTextObject::objectIndex() const
       
   156 {
       
   157     Q_D(const QTextObject);
       
   158     return d->objectIndex;
       
   159 }
       
   160 
       
   161 /*!
       
   162     Returns the document this object belongs to.
       
   163 
       
   164     \sa format()
       
   165 */
       
   166 QTextDocument *QTextObject::document() const
       
   167 {
       
   168     return static_cast<QTextDocument *>(parent());
       
   169 }
       
   170 
       
   171 /*!
       
   172   \internal
       
   173 */
       
   174 QTextDocumentPrivate *QTextObject::docHandle() const
       
   175 {
       
   176     return static_cast<const QTextDocument *>(parent())->docHandle();
       
   177 }
       
   178 
       
   179 /*!
       
   180     \class QTextBlockGroup
       
   181     \reentrant
       
   182 
       
   183     \brief The QTextBlockGroup class provides a container for text blocks within
       
   184     a QTextDocument.
       
   185 
       
   186     \ingroup richtext-processing
       
   187 
       
   188     Block groups can be used to organize blocks of text within a document.
       
   189     They maintain an up-to-date list of the text blocks that belong to
       
   190     them, even when text blocks are being edited.
       
   191 
       
   192     Each group has a parent document which is specified when the group is
       
   193     constructed.
       
   194 
       
   195     Text blocks can be inserted into a group with blockInserted(), and removed
       
   196     with blockRemoved(). If a block's format is changed, blockFormatChanged()
       
   197     is called.
       
   198 
       
   199     The list of blocks in the group is returned by blockList(). Note that the
       
   200     blocks in the list are not necessarily adjacent elements in the document;
       
   201     for example, the top-level items in a multi-level list will be separated
       
   202     by the items in lower levels of the list.
       
   203 
       
   204     \sa QTextBlock QTextDocument
       
   205 */
       
   206 
       
   207 void QTextBlockGroupPrivate::markBlocksDirty()
       
   208 {
       
   209     for (int i = 0; i < blocks.count(); ++i) {
       
   210         const QTextBlock &block = blocks.at(i);
       
   211         pieceTable->documentChange(block.position(), block.length());
       
   212     }
       
   213 }
       
   214 
       
   215 /*!
       
   216     \fn QTextBlockGroup::QTextBlockGroup(QTextDocument *document)
       
   217 
       
   218     Creates a new new block group for the given \a document.
       
   219 
       
   220     \warning This function should only be called from
       
   221     QTextDocument::createObject().
       
   222 */
       
   223 QTextBlockGroup::QTextBlockGroup(QTextDocument *doc)
       
   224     : QTextObject(*new QTextBlockGroupPrivate(doc), doc)
       
   225 {
       
   226 }
       
   227 
       
   228 /*!
       
   229   \internal
       
   230 */
       
   231 QTextBlockGroup::QTextBlockGroup(QTextBlockGroupPrivate &p, QTextDocument *doc)
       
   232     : QTextObject(p, doc)
       
   233 {
       
   234 }
       
   235 
       
   236 /*!
       
   237     Destroys this block group; the blocks are not deleted, they simply
       
   238     don't belong to this block anymore.
       
   239 */
       
   240 QTextBlockGroup::~QTextBlockGroup()
       
   241 {
       
   242 }
       
   243 
       
   244 // ### DOC: Shouldn't this be insertBlock()?
       
   245 /*!
       
   246     Appends the given \a block to the end of the group.
       
   247 
       
   248     \warning If you reimplement this function you must call the base
       
   249     class implementation.
       
   250 */
       
   251 void QTextBlockGroup::blockInserted(const QTextBlock &block)
       
   252 {
       
   253     Q_D(QTextBlockGroup);
       
   254     QTextBlockGroupPrivate::BlockList::Iterator it = qLowerBound(d->blocks.begin(), d->blocks.end(), block);
       
   255     d->blocks.insert(it, block);
       
   256     d->markBlocksDirty();
       
   257 }
       
   258 
       
   259 // ### DOC: Shouldn't this be removeBlock()?
       
   260 /*!
       
   261     Removes the given \a block from the group; the block itself is not
       
   262     deleted, it simply isn't a member of this group anymore.
       
   263 */
       
   264 void QTextBlockGroup::blockRemoved(const QTextBlock &block)
       
   265 {
       
   266     Q_D(QTextBlockGroup);
       
   267     d->blocks.removeAll(block);
       
   268     d->markBlocksDirty();
       
   269     if (d->blocks.isEmpty()) {
       
   270         document()->docHandle()->deleteObject(this);
       
   271         return;
       
   272     }
       
   273 }
       
   274 
       
   275 /*!
       
   276     This function is called whenever the specified \a block of text is changed.
       
   277     The text block is a member of this group.
       
   278 
       
   279     The base class implementation does nothing.
       
   280 */
       
   281 void QTextBlockGroup::blockFormatChanged(const QTextBlock &)
       
   282 {
       
   283 }
       
   284 
       
   285 /*!
       
   286     Returns a (possibly empty) list of all the blocks that are part of
       
   287     the block group.
       
   288 */
       
   289 QList<QTextBlock> QTextBlockGroup::blockList() const
       
   290 {
       
   291     Q_D(const QTextBlockGroup);
       
   292     return d->blocks;
       
   293 }
       
   294 
       
   295 
       
   296 
       
   297 QTextFrameLayoutData::~QTextFrameLayoutData()
       
   298 {
       
   299 }
       
   300 
       
   301 
       
   302 /*!
       
   303     \class QTextFrame
       
   304     \reentrant
       
   305 
       
   306     \brief The QTextFrame class represents a frame in a QTextDocument.
       
   307 
       
   308     \ingroup richtext-processing
       
   309 
       
   310     Text frames provide structure for the text in a document. They are used
       
   311     as generic containers for other document elements.
       
   312     Frames are usually created by using QTextCursor::insertFrame().
       
   313 
       
   314     \omit
       
   315     Each frame in a document consists of a frame start character,
       
   316     QChar(0xFDD0), followed by the frame's contents, followed by a
       
   317     frame end character, QChar(0xFDD1). The character formats of the
       
   318     start and end character contain a reference to the frame object's
       
   319     objectIndex.
       
   320     \endomit
       
   321 
       
   322     Frames can be used to create hierarchical structures in rich text documents.
       
   323     Each document has a root frame (QTextDocument::rootFrame()), and each frame
       
   324     beneath the root frame has a parent frame and a (possibly empty) list of
       
   325     child frames. The parent frame can be found with parentFrame(), and the
       
   326     childFrames() function provides a list of child frames.
       
   327 
       
   328     Each frame contains at least one text block to enable text cursors to
       
   329     insert new document elements within. As a result, the QTextFrame::iterator
       
   330     class is used to traverse both the blocks and child frames within a given
       
   331     frame. The first and last child elements in the frame can be found with
       
   332     begin() and end().
       
   333 
       
   334     A frame also has a format (specified using QTextFrameFormat) which can be set
       
   335     with setFormat() and read with format().
       
   336 
       
   337     Text cursors can be obtained that point to the first and last valid cursor
       
   338     positions within a frame; use the firstCursorPosition() and
       
   339     lastCursorPosition() functions for this. The frame's extent in the
       
   340     document can be found with firstPosition() and lastPosition().
       
   341 
       
   342     You can iterate over a frame's contents using the
       
   343     QTextFrame::iterator class: this provides read-only access to its
       
   344     internal list of text blocks and child frames.
       
   345 
       
   346     \sa QTextCursor QTextDocument
       
   347 */
       
   348 
       
   349 /*!
       
   350     \typedef QTextFrame::Iterator
       
   351 
       
   352     Qt-style synonym for QTextFrame::iterator.
       
   353 */
       
   354 
       
   355 /*!
       
   356     \fn QTextFrame *QTextFrame::iterator::parentFrame() const
       
   357 
       
   358     Returns the parent frame of the current frame.
       
   359 
       
   360     \sa currentFrame() QTextFrame::parentFrame()
       
   361 */
       
   362 
       
   363 /*!
       
   364     \fn bool QTextFrame::iterator::operator==(const iterator &other) const
       
   365 
       
   366     Retuns true if the iterator is the same as the \a other iterator;
       
   367     otherwise returns false.
       
   368 */
       
   369 
       
   370 /*!
       
   371     \fn bool QTextFrame::iterator::operator!=(const iterator &other) const
       
   372 
       
   373     Retuns true if the iterator is different from the \a other iterator;
       
   374     otherwise returns false.
       
   375 */
       
   376 
       
   377 /*!
       
   378     \fn QTextFrame::iterator QTextFrame::iterator::operator++(int)
       
   379 
       
   380     The postfix ++ operator (\c{i++}) advances the iterator to the
       
   381     next item in the text frame, and returns an iterator to the old item.
       
   382 */
       
   383 
       
   384 /*!
       
   385     \fn QTextFrame::iterator QTextFrame::iterator::operator--(int)
       
   386 
       
   387     The postfix -- operator (\c{i--}) makes the preceding item in the
       
   388     current frame, and returns an iterator to the old item.
       
   389 */
       
   390 
       
   391 /*!
       
   392     \fn void QTextFrame::setFrameFormat(const QTextFrameFormat &format)
       
   393 
       
   394     Sets the frame's \a format.
       
   395 
       
   396     \sa frameFormat()
       
   397 */
       
   398 
       
   399 /*!
       
   400     \fn QTextFrameFormat QTextFrame::frameFormat() const
       
   401 
       
   402     Returns the frame's format.
       
   403 
       
   404     \sa setFrameFormat()
       
   405 */
       
   406 
       
   407 /*!
       
   408     \fn QTextFrame::QTextFrame(QTextDocument *document)
       
   409 
       
   410     Creates a new empty frame for the text \a document.
       
   411 */
       
   412 QTextFrame::QTextFrame(QTextDocument *doc)
       
   413     : QTextObject(*new QTextFramePrivate(doc), doc)
       
   414 {
       
   415 }
       
   416 
       
   417 // ### DOC: What does this do to child frames?
       
   418 /*!
       
   419     Destroys the frame, and removes it from the document's layout.
       
   420 */
       
   421 QTextFrame::~QTextFrame()
       
   422 {
       
   423     Q_D(QTextFrame);
       
   424     delete d->layoutData;
       
   425 }
       
   426 
       
   427 /*!
       
   428     \internal
       
   429 */
       
   430 QTextFrame::QTextFrame(QTextFramePrivate &p, QTextDocument *doc)
       
   431     : QTextObject(p, doc)
       
   432 {
       
   433 }
       
   434 
       
   435 /*!
       
   436     Returns a (possibly empty) list of the frame's child frames.
       
   437 
       
   438     \sa parentFrame()
       
   439 */
       
   440 QList<QTextFrame *> QTextFrame::childFrames() const
       
   441 {
       
   442     Q_D(const QTextFrame);
       
   443     return d->childFrames;
       
   444 }
       
   445 
       
   446 /*!
       
   447     Returns the frame's parent frame. If the frame is the root frame of a
       
   448     document, this will return 0.
       
   449 
       
   450     \sa childFrames() QTextDocument::rootFrame()
       
   451 */
       
   452 QTextFrame *QTextFrame::parentFrame() const
       
   453 {
       
   454     Q_D(const QTextFrame);
       
   455     return d->parentFrame;
       
   456 }
       
   457 
       
   458 
       
   459 /*!
       
   460     Returns the first cursor position inside the frame.
       
   461 
       
   462     \sa lastCursorPosition() firstPosition() lastPosition()
       
   463 */
       
   464 QTextCursor QTextFrame::firstCursorPosition() const
       
   465 {
       
   466     Q_D(const QTextFrame);
       
   467     return QTextCursor(d->pieceTable, firstPosition());
       
   468 }
       
   469 
       
   470 /*!
       
   471     Returns the last cursor position inside the frame.
       
   472 
       
   473     \sa firstCursorPosition() firstPosition() lastPosition()
       
   474 */
       
   475 QTextCursor QTextFrame::lastCursorPosition() const
       
   476 {
       
   477     Q_D(const QTextFrame);
       
   478     return QTextCursor(d->pieceTable, lastPosition());
       
   479 }
       
   480 
       
   481 /*!
       
   482     Returns the first document position inside the frame.
       
   483 
       
   484     \sa lastPosition() firstCursorPosition() lastCursorPosition()
       
   485 */
       
   486 int QTextFrame::firstPosition() const
       
   487 {
       
   488     Q_D(const QTextFrame);
       
   489     if (!d->fragment_start)
       
   490         return 0;
       
   491     return d->pieceTable->fragmentMap().position(d->fragment_start) + 1;
       
   492 }
       
   493 
       
   494 /*!
       
   495     Returns the last document position inside the frame.
       
   496 
       
   497     \sa firstPosition() firstCursorPosition() lastCursorPosition()
       
   498 */
       
   499 int QTextFrame::lastPosition() const
       
   500 {
       
   501     Q_D(const QTextFrame);
       
   502     if (!d->fragment_end)
       
   503         return d->pieceTable->length() - 1;
       
   504     return d->pieceTable->fragmentMap().position(d->fragment_end);
       
   505 }
       
   506 
       
   507 /*!
       
   508   \internal
       
   509 */
       
   510 QTextFrameLayoutData *QTextFrame::layoutData() const
       
   511 {
       
   512     Q_D(const QTextFrame);
       
   513     return d->layoutData;
       
   514 }
       
   515 
       
   516 /*!
       
   517   \internal
       
   518 */
       
   519 void QTextFrame::setLayoutData(QTextFrameLayoutData *data)
       
   520 {
       
   521     Q_D(QTextFrame);
       
   522     delete d->layoutData;
       
   523     d->layoutData = data;
       
   524 }
       
   525 
       
   526 
       
   527 
       
   528 void QTextFramePrivate::fragmentAdded(const QChar &type, uint fragment)
       
   529 {
       
   530     if (type == QTextBeginningOfFrame) {
       
   531         Q_ASSERT(!fragment_start);
       
   532         fragment_start = fragment;
       
   533     } else if (type == QTextEndOfFrame) {
       
   534         Q_ASSERT(!fragment_end);
       
   535         fragment_end = fragment;
       
   536     } else if (type == QChar::ObjectReplacementCharacter) {
       
   537         Q_ASSERT(!fragment_start);
       
   538         Q_ASSERT(!fragment_end);
       
   539         fragment_start = fragment;
       
   540         fragment_end = fragment;
       
   541     } else {
       
   542         Q_ASSERT(false);
       
   543     }
       
   544 }
       
   545 
       
   546 void QTextFramePrivate::fragmentRemoved(const QChar &type, uint fragment)
       
   547 {
       
   548     Q_UNUSED(fragment); // --release warning
       
   549     if (type == QTextBeginningOfFrame) {
       
   550         Q_ASSERT(fragment_start == fragment);
       
   551         fragment_start = 0;
       
   552     } else if (type == QTextEndOfFrame) {
       
   553         Q_ASSERT(fragment_end == fragment);
       
   554         fragment_end = 0;
       
   555     } else if (type == QChar::ObjectReplacementCharacter) {
       
   556         Q_ASSERT(fragment_start == fragment);
       
   557         Q_ASSERT(fragment_end == fragment);
       
   558         fragment_start = 0;
       
   559         fragment_end = 0;
       
   560     } else {
       
   561         Q_ASSERT(false);
       
   562     }
       
   563     remove_me();
       
   564 }
       
   565 
       
   566 
       
   567 void QTextFramePrivate::remove_me()
       
   568 {
       
   569     Q_Q(QTextFrame);
       
   570     if (fragment_start == 0 && fragment_end == 0
       
   571         && !parentFrame) {
       
   572         q->document()->docHandle()->deleteObject(q);
       
   573         return;
       
   574     }
       
   575 
       
   576     if (!parentFrame)
       
   577         return;
       
   578 
       
   579     int index = parentFrame->d_func()->childFrames.indexOf(q);
       
   580 
       
   581     // iterator over all children and move them to the parent
       
   582     for (int i = 0; i < childFrames.size(); ++i) {
       
   583         QTextFrame *c = childFrames.at(i);
       
   584         parentFrame->d_func()->childFrames.insert(index, c);
       
   585         c->d_func()->parentFrame = parentFrame;
       
   586         ++index;
       
   587     }
       
   588     Q_ASSERT(parentFrame->d_func()->childFrames.at(index) == q);
       
   589     parentFrame->d_func()->childFrames.removeAt(index);
       
   590 
       
   591     childFrames.clear();
       
   592     parentFrame = 0;
       
   593 }
       
   594 
       
   595 /*!
       
   596     \class QTextFrame::iterator
       
   597     \reentrant
       
   598 
       
   599     \brief The iterator class provides an iterator for reading
       
   600     the contents of a QTextFrame.
       
   601 
       
   602     \ingroup richtext-processing
       
   603 
       
   604     A frame consists of an arbitrary sequence of \l{QTextBlock}s and
       
   605     child \l{QTextFrame}s. This class provides a way to iterate over the
       
   606     child objects of a frame, and read their contents. It does not provide
       
   607     a way to modify the contents of the frame.
       
   608 
       
   609 */
       
   610 
       
   611 /*!
       
   612     \fn bool QTextFrame::iterator::atEnd() const
       
   613 
       
   614     Returns true if the current item is the last item in the text frame.
       
   615 */
       
   616 
       
   617 /*!
       
   618     Returns an iterator pointing to the first document element inside the frame.
       
   619 
       
   620     \sa end()
       
   621 */
       
   622 QTextFrame::iterator QTextFrame::begin() const
       
   623 {
       
   624     const QTextDocumentPrivate *priv = docHandle();
       
   625     int b = priv->blockMap().findNode(firstPosition());
       
   626     int e = priv->blockMap().findNode(lastPosition()+1);
       
   627     return iterator(const_cast<QTextFrame *>(this), b, b, e);
       
   628 }
       
   629 
       
   630 /*!
       
   631     Returns an iterator pointing to the last document element inside the frame.
       
   632 
       
   633     \sa begin()
       
   634 */
       
   635 QTextFrame::iterator QTextFrame::end() const
       
   636 {
       
   637     const QTextDocumentPrivate *priv = docHandle();
       
   638     int b = priv->blockMap().findNode(firstPosition());
       
   639     int e = priv->blockMap().findNode(lastPosition()+1);
       
   640     return iterator(const_cast<QTextFrame *>(this), e, b, e);
       
   641 }
       
   642 
       
   643 /*!
       
   644     Constructs an invalid iterator.
       
   645 */
       
   646 QTextFrame::iterator::iterator()
       
   647 {
       
   648     f = 0;
       
   649     b = 0;
       
   650     e = 0;
       
   651     cf = 0;
       
   652     cb = 0;
       
   653 }
       
   654 
       
   655 /*!
       
   656   \internal
       
   657 */
       
   658 QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end)
       
   659 {
       
   660     f = frame;
       
   661     b = begin;
       
   662     e = end;
       
   663     cf = 0;
       
   664     cb = block;
       
   665 }
       
   666 
       
   667 /*!
       
   668     Copy constructor. Constructs a copy of the \a other iterator.
       
   669 */
       
   670 QTextFrame::iterator::iterator(const iterator &other)
       
   671 {
       
   672     f = other.f;
       
   673     b = other.b;
       
   674     e = other.e;
       
   675     cf = other.cf;
       
   676     cb = other.cb;
       
   677 }
       
   678 
       
   679 /*!
       
   680     Assigns \a other to this iterator and returns a reference to
       
   681     this iterator.
       
   682 */
       
   683 QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other)
       
   684 {
       
   685     f = other.f;
       
   686     b = other.b;
       
   687     e = other.e;
       
   688     cf = other.cf;
       
   689     cb = other.cb;
       
   690     return *this;
       
   691 }
       
   692 
       
   693 /*!
       
   694     Returns the current frame pointed to by the iterator, or 0 if the
       
   695     iterator currently points to a block.
       
   696 
       
   697     \sa currentBlock()
       
   698 */
       
   699 QTextFrame *QTextFrame::iterator::currentFrame() const
       
   700 {
       
   701     return cf;
       
   702 }
       
   703 
       
   704 /*!
       
   705     Returns the current block the iterator points to. If the iterator
       
   706     points to a child frame, the returned block is invalid.
       
   707 
       
   708     \sa currentFrame()
       
   709 */
       
   710 QTextBlock QTextFrame::iterator::currentBlock() const
       
   711 {
       
   712     if (!f)
       
   713         return QTextBlock();
       
   714     return QTextBlock(f->docHandle(), cb);
       
   715 }
       
   716 
       
   717 /*!
       
   718     Moves the iterator to the next frame or block.
       
   719 
       
   720     \sa currentBlock() currentFrame()
       
   721 */
       
   722 QTextFrame::iterator &QTextFrame::iterator::operator++()
       
   723 {
       
   724     const QTextDocumentPrivate *priv = f->docHandle();
       
   725     const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
       
   726     if (cf) {
       
   727         int end = cf->lastPosition() + 1;
       
   728         cb = map.findNode(end);
       
   729         cf = 0;
       
   730     } else if (cb) {
       
   731         cb = map.next(cb);
       
   732         if (cb == e)
       
   733             return *this;
       
   734 
       
   735         if (!f->d_func()->childFrames.isEmpty()) {
       
   736             int pos = map.position(cb);
       
   737             // check if we entered a frame
       
   738             QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
       
   739             if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
       
   740                 QTextFrame *nf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
       
   741                 if (nf) {
       
   742                     if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame && nf != f) {
       
   743                         cf = nf;
       
   744                         cb = 0;
       
   745                     } else {
       
   746                         Q_ASSERT(priv->buffer().at(frag->stringPosition) != QTextEndOfFrame);
       
   747                     }
       
   748                 }
       
   749             }
       
   750         }
       
   751     }
       
   752     return *this;
       
   753 }
       
   754 
       
   755 /*!
       
   756     Moves the iterator to the previous frame or block.
       
   757 
       
   758     \sa currentBlock() currentFrame()
       
   759 */
       
   760 QTextFrame::iterator &QTextFrame::iterator::operator--()
       
   761 {
       
   762     const QTextDocumentPrivate *priv = f->docHandle();
       
   763     const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
       
   764     if (cf) {
       
   765         int start = cf->firstPosition() - 1;
       
   766         cb = map.findNode(start);
       
   767         cf = 0;
       
   768     } else {
       
   769         if (cb == b)
       
   770             goto end;
       
   771         if (cb != e) {
       
   772             int pos = map.position(cb);
       
   773             // check if we have to enter a frame
       
   774             QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
       
   775             if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
       
   776                 QTextFrame *pf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
       
   777                 if (pf) {
       
   778                     if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame) {
       
   779                         Q_ASSERT(pf == f);
       
   780                     } else if (priv->buffer().at(frag->stringPosition) == QTextEndOfFrame) {
       
   781                         Q_ASSERT(pf != f);
       
   782                         cf = pf;
       
   783                         cb = 0;
       
   784                         goto end;
       
   785                     }
       
   786                 }
       
   787             }
       
   788         }
       
   789         cb = map.previous(cb);
       
   790     }
       
   791  end:
       
   792     return *this;
       
   793 }
       
   794 
       
   795 /*!
       
   796     \class QTextBlockUserData
       
   797     \reentrant
       
   798 
       
   799     \brief The QTextBlockUserData class is used to associate custom data with blocks of text.
       
   800     \since 4.1
       
   801 
       
   802     \ingroup richtext-processing
       
   803 
       
   804     QTextBlockUserData provides an abstract interface for container classes that are used
       
   805     to associate application-specific user data with text blocks in a QTextDocument.
       
   806 
       
   807     Generally, subclasses of this class provide functions to allow data to be stored
       
   808     and retrieved, and instances are attached to blocks of text using
       
   809     QTextBlock::setUserData(). This makes it possible to store additional data per text
       
   810     block in a way that can be retrieved safely by the application.
       
   811 
       
   812     Each subclass should provide a reimplementation of the destructor to ensure that any
       
   813     private data is automatically cleaned up when user data objects are deleted.
       
   814 
       
   815     \sa QTextBlock
       
   816 */
       
   817 
       
   818 /*!
       
   819     Destroys the user data.
       
   820 */
       
   821 QTextBlockUserData::~QTextBlockUserData()
       
   822 {
       
   823 }
       
   824 
       
   825 /*!
       
   826     \class QTextBlock
       
   827     \reentrant
       
   828 
       
   829     \brief The QTextBlock class provides a container for text fragments in a
       
   830     QTextDocument.
       
   831 
       
   832     \ingroup richtext-processing
       
   833 
       
   834     A text block encapsulates a block or paragraph of text in a QTextDocument.
       
   835     QTextBlock provides read-only access to the block/paragraph structure of
       
   836     QTextDocuments. It is mainly of use if you want to implement your own
       
   837     layouts for the visual representation of a QTextDocument, or if you want to
       
   838     iterate over a document and write out the contents in your own custom
       
   839     format.
       
   840 
       
   841     Text blocks are created by their parent documents. If you need to create
       
   842     a new text block, or modify the contents of a document while examining its
       
   843     contents, use the cursor-based interface provided by QTextCursor instead.
       
   844 
       
   845     Each text block is located at a specific position() in a document().
       
   846     The contents of the block can be obtained by using the text() function.
       
   847     The length() function determines the block's size within the document
       
   848     (including formatting characters).
       
   849     The visual properties of the block are determined by its text layout(),
       
   850     its charFormat(), and its blockFormat().
       
   851 
       
   852     The next() and previous() functions enable iteration over consecutive
       
   853     valid blocks in a document under the condition that the document is not
       
   854     modified by other means during the iteration process. Note that, although
       
   855     blocks are returned in sequence, adjacent blocks may come from different
       
   856     places in the document structure. The validity of a block can be determined
       
   857     by calling isValid().
       
   858 
       
   859     QTextBlock provides comparison operators to make it easier to work with
       
   860     blocks: \l operator==() compares two block for equality, \l operator!=()
       
   861     compares two blocks for inequality, and \l operator<() determines whether
       
   862     a block precedes another in the same document.
       
   863 
       
   864     \img qtextblock-sequence.png
       
   865 
       
   866     \sa QTextBlockFormat QTextCharFormat QTextFragment
       
   867  */
       
   868 
       
   869 /*!
       
   870     \fn QTextBlock::QTextBlock(QTextDocumentPrivate *priv, int b)
       
   871 
       
   872     \internal
       
   873 */
       
   874 
       
   875 /*!
       
   876     \fn QTextBlock::QTextBlock()
       
   877 
       
   878     \internal
       
   879 */
       
   880 
       
   881 /*!
       
   882     \fn QTextBlock::QTextBlock(const QTextBlock &other)
       
   883 
       
   884     Copies the \a other text block's attributes to this text block.
       
   885 */
       
   886 
       
   887 /*!
       
   888     \fn bool QTextBlock::isValid() const
       
   889 
       
   890     Returns true if this text block is valid; otherwise returns false.
       
   891 */
       
   892 
       
   893 /*!
       
   894     \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
       
   895 
       
   896     Assigns the \a other text block to this text block.
       
   897 */
       
   898 
       
   899 /*!
       
   900     \fn bool QTextBlock::operator==(const QTextBlock &other) const
       
   901 
       
   902     Returns true if this text block is the same as the \a other text
       
   903     block.
       
   904 */
       
   905 
       
   906 /*!
       
   907     \fn bool QTextBlock::operator!=(const QTextBlock &other) const
       
   908 
       
   909     Returns true if this text block is different from the \a other
       
   910     text block.
       
   911 */
       
   912 
       
   913 /*!
       
   914     \fn bool QTextBlock::operator<(const QTextBlock &other) const
       
   915 
       
   916     Returns true if this text block occurs before the \a other text
       
   917     block in the document.
       
   918 */
       
   919 
       
   920 /*!
       
   921     \class QTextBlock::iterator
       
   922     \reentrant
       
   923 
       
   924     \brief The QTextBlock::iterator class provides an iterator for reading
       
   925     the contents of a QTextBlock.
       
   926 
       
   927     \ingroup richtext-processing
       
   928 
       
   929     A block consists of a sequence of text fragments. This class provides
       
   930     a way to iterate over these, and read their contents. It does not provide
       
   931     a way to modify the internal structure or contents of the block.
       
   932 
       
   933     An iterator can be constructed and used to access the fragments within
       
   934     a text block in the following way:
       
   935 
       
   936     \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 4
       
   937     \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 7
       
   938 
       
   939     \sa QTextFragment
       
   940 */
       
   941 
       
   942 /*!
       
   943     \typedef QTextBlock::Iterator
       
   944 
       
   945     Qt-style synonym for QTextBlock::iterator.
       
   946 */
       
   947 
       
   948 /*!
       
   949     \fn QTextBlock::iterator::iterator()
       
   950 
       
   951     Constructs an iterator for this text block.
       
   952 */
       
   953 
       
   954 /*!
       
   955     \fn QTextBlock::iterator::iterator(const iterator &other)
       
   956 
       
   957     Copy constructor. Constructs a copy of the \a other iterator.
       
   958 */
       
   959 
       
   960 /*!
       
   961     \fn bool QTextBlock::iterator::atEnd() const
       
   962 
       
   963     Returns true if the current item is the last item in the text block.
       
   964 */
       
   965 
       
   966 /*!
       
   967     \fn bool QTextBlock::iterator::operator==(const iterator &other) const
       
   968 
       
   969     Retuns true if this iterator is the same as the \a other iterator;
       
   970     otherwise returns false.
       
   971 */
       
   972 
       
   973 /*!
       
   974     \fn bool QTextBlock::iterator::operator!=(const iterator &other) const
       
   975 
       
   976     Retuns true if this iterator is different from the \a other iterator;
       
   977     otherwise returns false.
       
   978 */
       
   979 
       
   980 /*!
       
   981     \fn QTextBlock::iterator QTextBlock::iterator::operator++(int)
       
   982 
       
   983     The postfix ++ operator (\c{i++}) advances the iterator to the
       
   984     next item in the text block and returns an iterator to the old current
       
   985     item.
       
   986 */
       
   987 
       
   988 /*!
       
   989     \fn QTextBlock::iterator QTextBlock::iterator::operator--(int)
       
   990 
       
   991     The postfix -- operator (\c{i--}) makes the preceding item current and
       
   992     returns an iterator to the old current item.
       
   993 */
       
   994 
       
   995 /*!
       
   996     \fn QTextDocumentPrivate *QTextBlock::docHandle() const
       
   997 
       
   998     \internal
       
   999 */
       
  1000 
       
  1001 /*!
       
  1002     \fn int QTextBlock::fragmentIndex() const
       
  1003 
       
  1004     \internal
       
  1005 */
       
  1006 
       
  1007 /*!
       
  1008     Returns the index of the block's first character within the document.
       
  1009  */
       
  1010 int QTextBlock::position() const
       
  1011 {
       
  1012     if (!p || !n)
       
  1013         return 0;
       
  1014 
       
  1015     return p->blockMap().position(n);
       
  1016 }
       
  1017 
       
  1018 /*!
       
  1019     Returns the length of the block in characters.
       
  1020 
       
  1021     \note The length returned includes all formatting characters,
       
  1022     for example, newline.
       
  1023 
       
  1024     \sa text() charFormat() blockFormat()
       
  1025  */
       
  1026 int QTextBlock::length() const
       
  1027 {
       
  1028     if (!p || !n)
       
  1029         return 0;
       
  1030 
       
  1031     return p->blockMap().size(n);
       
  1032 }
       
  1033 
       
  1034 /*!
       
  1035     Returns true if the given \a position is located within the text
       
  1036     block; otherwise returns false.
       
  1037  */
       
  1038 bool QTextBlock::contains(int position) const
       
  1039 {
       
  1040     if (!p || !n)
       
  1041         return false;
       
  1042 
       
  1043     int pos = p->blockMap().position(n);
       
  1044     int len = p->blockMap().size(n);
       
  1045     return position >= pos && position < pos + len;
       
  1046 }
       
  1047 
       
  1048 /*!
       
  1049     Returns the QTextLayout that is used to lay out and display the
       
  1050     block's contents.
       
  1051 
       
  1052     Note that the returned QTextLayout object can only be modified from the
       
  1053     documentChanged implementation of a QAbstractTextDocumentLayout subclass.
       
  1054     Any changes applied from the outside cause undefined behavior.
       
  1055 
       
  1056     \sa clearLayout()
       
  1057  */
       
  1058 QTextLayout *QTextBlock::layout() const
       
  1059 {
       
  1060     if (!p || !n)
       
  1061         return 0;
       
  1062 
       
  1063     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1064     if (!b->layout)
       
  1065         b->layout = new QTextLayout(*this);
       
  1066     return b->layout;
       
  1067 }
       
  1068 
       
  1069 /*!
       
  1070     \since 4.4
       
  1071     Clears the QTextLayout that is used to lay out and display the
       
  1072     block's contents.
       
  1073 
       
  1074     \sa layout()
       
  1075  */
       
  1076 void QTextBlock::clearLayout()
       
  1077 {
       
  1078     if (!p || !n)
       
  1079         return;
       
  1080 
       
  1081     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1082     if (b->layout)
       
  1083         b->layout->clearLayout();
       
  1084 }
       
  1085 
       
  1086 /*!
       
  1087     Returns the QTextBlockFormat that describes block-specific properties.
       
  1088 
       
  1089     \sa charFormat()
       
  1090  */
       
  1091 QTextBlockFormat QTextBlock::blockFormat() const
       
  1092 {
       
  1093     if (!p || !n)
       
  1094         return QTextFormat().toBlockFormat();
       
  1095 
       
  1096     return p->formatCollection()->blockFormat(p->blockMap().fragment(n)->format);
       
  1097 }
       
  1098 
       
  1099 /*!
       
  1100     Returns an index into the document's internal list of block formats
       
  1101     for the text block's format.
       
  1102 
       
  1103     \sa QTextDocument::allFormats()
       
  1104 */
       
  1105 int QTextBlock::blockFormatIndex() const
       
  1106 {
       
  1107     if (!p || !n)
       
  1108         return -1;
       
  1109 
       
  1110     return p->blockMap().fragment(n)->format;
       
  1111 }
       
  1112 
       
  1113 /*!
       
  1114     Returns the QTextCharFormat that describes the block's character
       
  1115     format. The block's character format is used when inserting text into
       
  1116     an empty block.
       
  1117 
       
  1118     \sa blockFormat()
       
  1119  */
       
  1120 QTextCharFormat QTextBlock::charFormat() const
       
  1121 {
       
  1122     if (!p || !n)
       
  1123         return QTextFormat().toCharFormat();
       
  1124 
       
  1125     return p->formatCollection()->charFormat(charFormatIndex());
       
  1126 }
       
  1127 
       
  1128 /*!
       
  1129     Returns an index into the document's internal list of character formats
       
  1130     for the text block's character format.
       
  1131 
       
  1132     \sa QTextDocument::allFormats()
       
  1133 */
       
  1134 int QTextBlock::charFormatIndex() const
       
  1135 {
       
  1136     if (!p || !n)
       
  1137         return -1;
       
  1138 
       
  1139     return p->blockCharFormatIndex(n);
       
  1140 }
       
  1141 
       
  1142 /*!
       
  1143     Returns the block's contents as plain text.
       
  1144 
       
  1145     \sa length() charFormat() blockFormat()
       
  1146  */
       
  1147 QString QTextBlock::text() const
       
  1148 {
       
  1149     if (!p || !n)
       
  1150         return QString();
       
  1151 
       
  1152     const QString buffer = p->buffer();
       
  1153     QString text;
       
  1154     text.reserve(length());
       
  1155 
       
  1156     const int pos = position();
       
  1157     QTextDocumentPrivate::FragmentIterator it = p->find(pos);
       
  1158     QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
       
  1159     for (; it != end; ++it) {
       
  1160         const QTextFragmentData * const frag = it.value();
       
  1161         text += QString::fromRawData(buffer.constData() + frag->stringPosition, frag->size_array[0]);
       
  1162     }
       
  1163 
       
  1164     return text;
       
  1165 }
       
  1166 
       
  1167 
       
  1168 /*!
       
  1169     Returns the text document this text block belongs to, or 0 if the
       
  1170     text block does not belong to any document.
       
  1171 */
       
  1172 const QTextDocument *QTextBlock::document() const
       
  1173 {
       
  1174     return p ? p->document() : 0;
       
  1175 }
       
  1176 
       
  1177 /*!
       
  1178     If the block represents a list item, returns the list that the item belongs
       
  1179     to; otherwise returns 0.
       
  1180 */
       
  1181 QTextList *QTextBlock::textList() const
       
  1182 {
       
  1183     if (!isValid())
       
  1184         return 0;
       
  1185 
       
  1186     const QTextBlockFormat fmt = blockFormat();
       
  1187     QTextObject *obj = p->document()->objectForFormat(fmt);
       
  1188     return qobject_cast<QTextList *>(obj);
       
  1189 }
       
  1190 
       
  1191 /*!
       
  1192     \since 4.1
       
  1193 
       
  1194     Returns a pointer to a QTextBlockUserData object if previously set with
       
  1195     setUserData() or a null pointer.
       
  1196 */
       
  1197 QTextBlockUserData *QTextBlock::userData() const
       
  1198 {
       
  1199     if (!p || !n)
       
  1200         return 0;
       
  1201 
       
  1202     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1203     return b->userData;
       
  1204 }
       
  1205 
       
  1206 /*!
       
  1207     \since 4.1
       
  1208 
       
  1209     Attaches the given \a data object to the text block.
       
  1210 
       
  1211     QTextBlockUserData can be used to store custom settings.  The
       
  1212     ownership is passed to the underlying text document, i.e. the
       
  1213     provided QTextBlockUserData object will be deleted if the
       
  1214     corresponding text block gets deleted. The user data object is
       
  1215     not stored in the undo history, so it will not be available after
       
  1216     undoing the deletion of a text block.
       
  1217 
       
  1218     For example, if you write a programming editor in an IDE, you may
       
  1219     want to let your user set breakpoints visually in your code for an
       
  1220     integrated debugger. In a programming editor a line of text
       
  1221     usually corresponds to one QTextBlock. The QTextBlockUserData
       
  1222     interface allows the developer to store data for each QTextBlock,
       
  1223     like for example in which lines of the source code the user has a
       
  1224     breakpoint set. Of course this could also be stored externally,
       
  1225     but by storing it inside the QTextDocument, it will for example be
       
  1226     automatically deleted when the user deletes the associated
       
  1227     line. It's really just a way to store custom information in the
       
  1228     QTextDocument without using custom properties in QTextFormat which
       
  1229     would affect the undo/redo stack.
       
  1230 */
       
  1231 void QTextBlock::setUserData(QTextBlockUserData *data)
       
  1232 {
       
  1233     if (!p || !n)
       
  1234         return;
       
  1235 
       
  1236     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1237     if (data != b->userData)
       
  1238         delete b->userData;
       
  1239     b->userData = data;
       
  1240 }
       
  1241 
       
  1242 /*!
       
  1243     \since 4.1
       
  1244 
       
  1245     Returns the integer value previously set with setUserState() or -1.
       
  1246 */
       
  1247 int QTextBlock::userState() const
       
  1248 {
       
  1249     if (!p || !n)
       
  1250         return -1;
       
  1251 
       
  1252     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1253     return b->userState;
       
  1254 }
       
  1255 
       
  1256 /*!
       
  1257     \since 4.1
       
  1258 
       
  1259     Stores the specified \a state integer value in the text block. This may be
       
  1260     useful for example in a syntax highlighter to store a text parsing state.
       
  1261 */
       
  1262 void QTextBlock::setUserState(int state)
       
  1263 {
       
  1264     if (!p || !n)
       
  1265         return;
       
  1266 
       
  1267     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1268     b->userState = state;
       
  1269 }
       
  1270 
       
  1271 /*!
       
  1272     \since 4.4
       
  1273 
       
  1274     Returns the blocks revision.
       
  1275 
       
  1276     \sa setRevision(), QTextDocument::revision()
       
  1277 */
       
  1278 int QTextBlock::revision() const
       
  1279 {
       
  1280     if (!p || !n)
       
  1281         return -1;
       
  1282 
       
  1283     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1284     return b->revision;
       
  1285 }
       
  1286 
       
  1287 /*!
       
  1288     \since 4.4
       
  1289 
       
  1290     Sets a blocks revision to \a rev.
       
  1291 
       
  1292     \sa revision(), QTextDocument::revision()
       
  1293 */
       
  1294 void QTextBlock::setRevision(int rev)
       
  1295 {
       
  1296     if (!p || !n)
       
  1297         return;
       
  1298 
       
  1299     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1300     b->revision = rev;
       
  1301 }
       
  1302 
       
  1303 /*!
       
  1304     \since 4.4
       
  1305 
       
  1306     Returns true if the block is visible; otherwise returns false.
       
  1307 
       
  1308     \sa setVisible()
       
  1309 */
       
  1310 bool QTextBlock::isVisible() const
       
  1311 {
       
  1312     if (!p || !n)
       
  1313         return true;
       
  1314 
       
  1315     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1316     return !b->hidden;
       
  1317 }
       
  1318 
       
  1319 /*!
       
  1320     \since 4.4
       
  1321 
       
  1322     Sets the block's visibility to \a visible.
       
  1323 
       
  1324     \sa isVisible()
       
  1325 */
       
  1326 void QTextBlock::setVisible(bool visible)
       
  1327 {
       
  1328     if (!p || !n)
       
  1329         return;
       
  1330 
       
  1331     const QTextBlockData *b = p->blockMap().fragment(n);
       
  1332     b->hidden = !visible;
       
  1333 }
       
  1334 
       
  1335 
       
  1336 /*!
       
  1337 \since 4.4
       
  1338 
       
  1339     Returns the number of this block, or -1 if the block is invalid.
       
  1340 
       
  1341     \sa QTextCursor::blockNumber()
       
  1342 
       
  1343 */
       
  1344 int QTextBlock::blockNumber() const
       
  1345 {
       
  1346     if (!p || !n)
       
  1347         return -1;
       
  1348     return p->blockMap().position(n, 1);
       
  1349 }
       
  1350 
       
  1351 /*!
       
  1352 \since 4.5
       
  1353 
       
  1354     Returns the first line number of this block, or -1 if the block is invalid.
       
  1355     Unless the layout supports it, the line number is identical to the block number.
       
  1356 
       
  1357     \sa QTextBlock::blockNumber()
       
  1358 
       
  1359 */
       
  1360 int QTextBlock::firstLineNumber() const
       
  1361 {
       
  1362     if (!p || !n)
       
  1363         return -1;
       
  1364     return p->blockMap().position(n, 2);
       
  1365 }
       
  1366 
       
  1367 
       
  1368 /*!
       
  1369 \since 4.5
       
  1370 
       
  1371 Sets the line count to \a count.
       
  1372 
       
  1373 \sa lineCount()
       
  1374 */
       
  1375 void QTextBlock::setLineCount(int count)
       
  1376 {
       
  1377     if (!p || !n)
       
  1378         return;
       
  1379     p->blockMap().setSize(n, count, 2);
       
  1380 }
       
  1381 /*!
       
  1382 \since 4.5
       
  1383 
       
  1384 Returns the line count. Not all document layouts support this feature.
       
  1385 
       
  1386 \sa setLineCount()
       
  1387  */
       
  1388 int QTextBlock::lineCount() const
       
  1389 {
       
  1390     if (!p || !n)
       
  1391         return -1;
       
  1392     return p->blockMap().size(n, 2);
       
  1393 }
       
  1394 
       
  1395 
       
  1396 /*!
       
  1397     Returns a text block iterator pointing to the beginning of the
       
  1398     text block.
       
  1399 
       
  1400     \sa end()
       
  1401 */
       
  1402 QTextBlock::iterator QTextBlock::begin() const
       
  1403 {
       
  1404     if (!p || !n)
       
  1405         return iterator();
       
  1406 
       
  1407     int pos = position();
       
  1408     int len = length() - 1; // exclude the fragment that holds the paragraph separator
       
  1409     int b = p->fragmentMap().findNode(pos);
       
  1410     int e = p->fragmentMap().findNode(pos+len);
       
  1411     return iterator(p, b, e, b);
       
  1412 }
       
  1413 
       
  1414 /*!
       
  1415     Returns a text block iterator pointing to the end of the text
       
  1416     block.
       
  1417 
       
  1418     \sa begin() next() previous()
       
  1419 */
       
  1420 QTextBlock::iterator QTextBlock::end() const
       
  1421 {
       
  1422     if (!p || !n)
       
  1423         return iterator();
       
  1424 
       
  1425     int pos = position();
       
  1426     int len = length() - 1; // exclude the fragment that holds the paragraph separator
       
  1427     int b = p->fragmentMap().findNode(pos);
       
  1428     int e = p->fragmentMap().findNode(pos+len);
       
  1429     return iterator(p, b, e, e);
       
  1430 }
       
  1431 
       
  1432 
       
  1433 /*!
       
  1434     Returns the text block in the document after this block, or an empty
       
  1435     text block if this is the last one.
       
  1436 
       
  1437     Note that the next block may be in a different frame or table to this block.
       
  1438 
       
  1439     \sa previous() begin() end()
       
  1440 */
       
  1441 QTextBlock QTextBlock::next() const
       
  1442 {
       
  1443     if (!p)
       
  1444         return QTextBlock();
       
  1445 
       
  1446     return QTextBlock(p, p->blockMap().next(n));
       
  1447 }
       
  1448 
       
  1449 /*!
       
  1450     Returns the text block in the document before this block, or an empty text
       
  1451     block if this is the first one.
       
  1452 
       
  1453     Note that the next block may be in a different frame or table to this block.
       
  1454 
       
  1455     \sa next() begin() end()
       
  1456 */
       
  1457 QTextBlock QTextBlock::previous() const
       
  1458 {
       
  1459     if (!p)
       
  1460         return QTextBlock();
       
  1461 
       
  1462     return QTextBlock(p, p->blockMap().previous(n));
       
  1463 }
       
  1464 
       
  1465 
       
  1466 /*!
       
  1467     Returns the text fragment the iterator currently points to.
       
  1468 */
       
  1469 QTextFragment QTextBlock::iterator::fragment() const
       
  1470 {
       
  1471     int ne = n;
       
  1472     int formatIndex = p->fragmentMap().fragment(n)->format;
       
  1473     do {
       
  1474         ne = p->fragmentMap().next(ne);
       
  1475     } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
       
  1476     return QTextFragment(p, n, ne);
       
  1477 }
       
  1478 
       
  1479 /*!
       
  1480     The prefix ++ operator (\c{++i}) advances the iterator to the
       
  1481     next item in the hash and returns an iterator to the new current
       
  1482     item.
       
  1483 */
       
  1484 
       
  1485 QTextBlock::iterator &QTextBlock::iterator::operator++()
       
  1486 {
       
  1487     int ne = n;
       
  1488     int formatIndex = p->fragmentMap().fragment(n)->format;
       
  1489     do {
       
  1490         ne = p->fragmentMap().next(ne);
       
  1491     } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
       
  1492     n = ne;
       
  1493     return *this;
       
  1494 }
       
  1495 
       
  1496 /*!
       
  1497     The prefix -- operator (\c{--i}) makes the preceding item
       
  1498     current and returns an iterator pointing to the new current item.
       
  1499 */
       
  1500 
       
  1501 QTextBlock::iterator &QTextBlock::iterator::operator--()
       
  1502 {
       
  1503     n = p->fragmentMap().previous(n);
       
  1504 
       
  1505     if (n == b)
       
  1506         return *this;
       
  1507 
       
  1508     int formatIndex = p->fragmentMap().fragment(n)->format;
       
  1509     int last = n;
       
  1510 
       
  1511     while (n != b && p->fragmentMap().fragment(n)->format != formatIndex) {
       
  1512         last = n;
       
  1513         n = p->fragmentMap().previous(n);
       
  1514     }
       
  1515 
       
  1516     n = last;
       
  1517     return *this;
       
  1518 }
       
  1519 
       
  1520 
       
  1521 /*!
       
  1522     \class QTextFragment
       
  1523     \reentrant
       
  1524 
       
  1525     \brief The QTextFragment class holds a piece of text in a
       
  1526     QTextDocument with a single QTextCharFormat.
       
  1527 
       
  1528     \ingroup richtext-processing
       
  1529 
       
  1530     A text fragment describes a piece of text that is stored with a single
       
  1531     character format. Text in which the character format changes can be
       
  1532     represented by sequences of text fragments with different formats.
       
  1533 
       
  1534     If the user edits the text in a fragment and introduces a different
       
  1535     character format, the fragment's text will be split at each point where
       
  1536     the format changes, and new fragments will be created.
       
  1537     For example, changing the style of some text in the middle of a
       
  1538     sentence will cause the fragment to be broken into three separate fragments:
       
  1539     the first and third with the same format as before, and the second with
       
  1540     the new style. The first fragment will contain the text from the beginning
       
  1541     of the sentence, the second will contain the text from the middle, and the
       
  1542     third takes the text from the end of the sentence.
       
  1543 
       
  1544     \img qtextfragment-split.png
       
  1545 
       
  1546     A fragment's text and character format can be obtained with the text()
       
  1547     and charFormat() functions. The length() function gives the length of
       
  1548     the text in the fragment. position() gives the position in the document
       
  1549     of the start of the fragment. To determine whether the fragment contains
       
  1550     a particular position within the document, use the contains() function.
       
  1551 
       
  1552     \sa QTextDocument, {Rich Text Document Structure}
       
  1553 */
       
  1554 
       
  1555 /*!
       
  1556     \fn QTextFragment::QTextFragment(const QTextDocumentPrivate *priv, int f, int fe)
       
  1557     \internal
       
  1558 */
       
  1559 
       
  1560 /*!
       
  1561     \fn QTextFragment::QTextFragment()
       
  1562 
       
  1563     Creates a new empty text fragment.
       
  1564 */
       
  1565 
       
  1566 /*!
       
  1567     \fn QTextFragment::QTextFragment(const QTextFragment &other)
       
  1568 
       
  1569     Copies the content (text and format) of the \a other text fragment
       
  1570     to this text fragment.
       
  1571 */
       
  1572 
       
  1573 /*!
       
  1574     \fn QTextFragment &QTextFragment::operator=(const QTextFragment
       
  1575     &other)
       
  1576 
       
  1577     Assigns the content (text and format) of the \a other text fragment
       
  1578     to this text fragment.
       
  1579 */
       
  1580 
       
  1581 /*!
       
  1582     \fn bool QTextFragment::isValid() const
       
  1583 
       
  1584     Returns true if this is a valid text fragment (i.e. has a valid
       
  1585     position in a document); otherwise returns false.
       
  1586 */
       
  1587 
       
  1588 /*!
       
  1589     \fn bool QTextFragment::operator==(const QTextFragment &other) const
       
  1590 
       
  1591     Returns true if this text fragment is the same (at the same
       
  1592     position) as the \a other text fragment; otherwise returns false.
       
  1593 */
       
  1594 
       
  1595 /*!
       
  1596     \fn bool QTextFragment::operator!=(const QTextFragment &other) const
       
  1597 
       
  1598     Returns true if this text fragment is different (at a different
       
  1599     position) from the \a other text fragment; otherwise returns
       
  1600     false.
       
  1601 */
       
  1602 
       
  1603 /*!
       
  1604     \fn bool QTextFragment::operator<(const QTextFragment &other) const
       
  1605 
       
  1606     Returns true if this text fragment appears earlier in the document
       
  1607     than the \a other text fragment; otherwise returns false.
       
  1608 */
       
  1609 
       
  1610 
       
  1611 /*!
       
  1612     Returns the position of this text fragment in the document.
       
  1613 */
       
  1614 int QTextFragment::position() const
       
  1615 {
       
  1616     if (!p || !n)
       
  1617         return 0; // ### -1 instead?
       
  1618 
       
  1619     return p->fragmentMap().position(n);
       
  1620 }
       
  1621 
       
  1622 /*!
       
  1623     Returns the number of characters in the text fragment.
       
  1624 
       
  1625     \sa text()
       
  1626 */
       
  1627 int QTextFragment::length() const
       
  1628 {
       
  1629     if (!p || !n)
       
  1630         return 0;
       
  1631 
       
  1632     int len = 0;
       
  1633     int f = n;
       
  1634     while (f != ne) {
       
  1635         len += p->fragmentMap().size(f);
       
  1636         f = p->fragmentMap().next(f);
       
  1637     }
       
  1638     return len;
       
  1639 }
       
  1640 
       
  1641 /*!
       
  1642     Returns true if the text fragment contains the text at the given
       
  1643     \a position in the document; otherwise returns false.
       
  1644 */
       
  1645 bool QTextFragment::contains(int position) const
       
  1646 {
       
  1647     if (!p || !n)
       
  1648         return false;
       
  1649     int pos = this->position();
       
  1650     return position >= pos && position < pos + length();
       
  1651 }
       
  1652 
       
  1653 /*!
       
  1654     Returns the text fragment's character format.
       
  1655 
       
  1656     \sa text()
       
  1657 */
       
  1658 QTextCharFormat QTextFragment::charFormat() const
       
  1659 {
       
  1660     if (!p || !n)
       
  1661         return QTextCharFormat();
       
  1662     const QTextFragmentData *data = p->fragmentMap().fragment(n);
       
  1663     return p->formatCollection()->charFormat(data->format);
       
  1664 }
       
  1665 
       
  1666 /*!
       
  1667     Returns an index into the document's internal list of character formats
       
  1668     for the text fragment's character format.
       
  1669 
       
  1670     \sa QTextDocument::allFormats()
       
  1671 */
       
  1672 int QTextFragment::charFormatIndex() const
       
  1673 {
       
  1674     if (!p || !n)
       
  1675         return -1;
       
  1676     const QTextFragmentData *data = p->fragmentMap().fragment(n);
       
  1677     return data->format;
       
  1678 }
       
  1679 
       
  1680 /*!
       
  1681     Returns the text fragment's as plain text.
       
  1682 
       
  1683     \sa length(), charFormat()
       
  1684 */
       
  1685 QString QTextFragment::text() const
       
  1686 {
       
  1687     if (!p || !n)
       
  1688         return QString();
       
  1689 
       
  1690     QString result;
       
  1691     QString buffer = p->buffer();
       
  1692     int f = n;
       
  1693     while (f != ne) {
       
  1694         const QTextFragmentData * const frag = p->fragmentMap().fragment(f);
       
  1695         result += QString(buffer.constData() + frag->stringPosition, frag->size_array[0]);
       
  1696         f = p->fragmentMap().next(f);
       
  1697     }
       
  1698     return result;
       
  1699 }
       
  1700 
       
  1701 QT_END_NAMESPACE