1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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 */
QTextObject(QTextDocument * doc)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 */
QTextObject(QTextObjectPrivate & p,QTextDocument * doc)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 */
~QTextObject()111 QTextObject::~QTextObject()
112 {
113 }
114 
115 /*!
116     Returns the text object's format.
117 
118     \sa setFormat() document()
119 */
format() const120 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 */
formatIndex() const132 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 */
setFormat(const QTextFormat & format)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 */
objectIndex() const155 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 */
document() const166 QTextDocument *QTextObject::document() const
167 {
168     return static_cast<QTextDocument *>(parent());
169 }
170 
171 /*!
172   \internal
173 */
docHandle() const174 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 
markBlocksDirty()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 */
QTextBlockGroup(QTextDocument * doc)223 QTextBlockGroup::QTextBlockGroup(QTextDocument *doc)
224     : QTextObject(*new QTextBlockGroupPrivate(doc), doc)
225 {
226 }
227 
228 /*!
229   \internal
230 */
QTextBlockGroup(QTextBlockGroupPrivate & p,QTextDocument * doc)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 */
~QTextBlockGroup()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 */
blockInserted(const QTextBlock & block)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 */
blockRemoved(const QTextBlock & block)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 */
blockFormatChanged(const QTextBlock &)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 */
blockList() const289 QList<QTextBlock> QTextBlockGroup::blockList() const
290 {
291     Q_D(const QTextBlockGroup);
292     return d->blocks;
293 }
294 
295 
296 
~QTextFrameLayoutData()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 */
QTextFrame(QTextDocument * doc)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 */
~QTextFrame()421 QTextFrame::~QTextFrame()
422 {
423     Q_D(QTextFrame);
424     delete d->layoutData;
425 }
426 
427 /*!
428     \internal
429 */
QTextFrame(QTextFramePrivate & p,QTextDocument * doc)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 */
childFrames() const440 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 */
parentFrame() const452 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 */
firstCursorPosition() const464 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 */
lastCursorPosition() const475 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 */
firstPosition() const486 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 */
lastPosition() const499 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 */
layoutData() const510 QTextFrameLayoutData *QTextFrame::layoutData() const
511 {
512     Q_D(const QTextFrame);
513     return d->layoutData;
514 }
515 
516 /*!
517   \internal
518 */
setLayoutData(QTextFrameLayoutData * data)519 void QTextFrame::setLayoutData(QTextFrameLayoutData *data)
520 {
521     Q_D(QTextFrame);
522     delete d->layoutData;
523     d->layoutData = data;
524 }
525 
526 
527 
fragmentAdded(const QChar & type,uint fragment)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 
fragmentRemoved(const QChar & type,uint fragment)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 
remove_me()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     Please see the document \l{STL-style-Iterators} for more information.
620 
621     \sa end()
622 */
begin() const623 QTextFrame::iterator QTextFrame::begin() const
624 {
625     const QTextDocumentPrivate *priv = docHandle();
626     int b = priv->blockMap().findNode(firstPosition());
627     int e = priv->blockMap().findNode(lastPosition()+1);
628     return iterator(const_cast<QTextFrame *>(this), b, b, e);
629 }
630 
631 /*!
632     Returns an iterator pointing to the position past the last document element inside the frame.
633     Please see the document \l{STL-Style Iterators} for more information.
634     \sa begin()
635 */
end() const636 QTextFrame::iterator QTextFrame::end() const
637 {
638     const QTextDocumentPrivate *priv = docHandle();
639     int b = priv->blockMap().findNode(firstPosition());
640     int e = priv->blockMap().findNode(lastPosition()+1);
641     return iterator(const_cast<QTextFrame *>(this), e, b, e);
642 }
643 
644 /*!
645     Constructs an invalid iterator.
646 */
iterator()647 QTextFrame::iterator::iterator()
648 {
649     f = 0;
650     b = 0;
651     e = 0;
652     cf = 0;
653     cb = 0;
654 }
655 
656 /*!
657   \internal
658 */
iterator(QTextFrame * frame,int block,int begin,int end)659 QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end)
660 {
661     f = frame;
662     b = begin;
663     e = end;
664     cf = 0;
665     cb = block;
666 }
667 
668 /*!
669     Copy constructor. Constructs a copy of the \a other iterator.
670 */
iterator(const iterator & other)671 QTextFrame::iterator::iterator(const iterator &other)
672 {
673     f = other.f;
674     b = other.b;
675     e = other.e;
676     cf = other.cf;
677     cb = other.cb;
678 }
679 
680 /*!
681     Assigns \a other to this iterator and returns a reference to
682     this iterator.
683 */
operator =(const iterator & other)684 QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other)
685 {
686     f = other.f;
687     b = other.b;
688     e = other.e;
689     cf = other.cf;
690     cb = other.cb;
691     return *this;
692 }
693 
694 /*!
695     Returns the current frame pointed to by the iterator, or 0 if the
696     iterator currently points to a block.
697 
698     \sa currentBlock()
699 */
currentFrame() const700 QTextFrame *QTextFrame::iterator::currentFrame() const
701 {
702     return cf;
703 }
704 
705 /*!
706     Returns the current block the iterator points to. If the iterator
707     points to a child frame, the returned block is invalid.
708 
709     \sa currentFrame()
710 */
currentBlock() const711 QTextBlock QTextFrame::iterator::currentBlock() const
712 {
713     if (!f)
714         return QTextBlock();
715     return QTextBlock(f->docHandle(), cb);
716 }
717 
718 /*!
719     Moves the iterator to the next frame or block.
720 
721     \sa currentBlock() currentFrame()
722 */
operator ++()723 QTextFrame::iterator &QTextFrame::iterator::operator++()
724 {
725     const QTextDocumentPrivate *priv = f->docHandle();
726     const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
727     if (cf) {
728         int end = cf->lastPosition() + 1;
729         cb = map.findNode(end);
730         cf = 0;
731     } else if (cb) {
732         cb = map.next(cb);
733         if (cb == e)
734             return *this;
735 
736         if (!f->d_func()->childFrames.isEmpty()) {
737             int pos = map.position(cb);
738             // check if we entered a frame
739             QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
740             if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
741                 QTextFrame *nf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
742                 if (nf) {
743                     if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame && nf != f) {
744                         cf = nf;
745                         cb = 0;
746                     } else {
747                         Q_ASSERT(priv->buffer().at(frag->stringPosition) != QTextEndOfFrame);
748                     }
749                 }
750             }
751         }
752     }
753     return *this;
754 }
755 
756 /*!
757     Moves the iterator to the previous frame or block.
758 
759     \sa currentBlock() currentFrame()
760 */
operator --()761 QTextFrame::iterator &QTextFrame::iterator::operator--()
762 {
763     const QTextDocumentPrivate *priv = f->docHandle();
764     const QTextDocumentPrivate::BlockMap &map = priv->blockMap();
765     if (cf) {
766         int start = cf->firstPosition() - 1;
767         cb = map.findNode(start);
768         cf = 0;
769     } else {
770         if (cb == b)
771             goto end;
772         if (cb != e) {
773             int pos = map.position(cb);
774             // check if we have to enter a frame
775             QTextDocumentPrivate::FragmentIterator frag = priv->find(pos-1);
776             if (priv->buffer().at(frag->stringPosition) != QChar::ParagraphSeparator) {
777                 QTextFrame *pf = qobject_cast<QTextFrame *>(priv->objectForFormat(frag->format));
778                 if (pf) {
779                     if (priv->buffer().at(frag->stringPosition) == QTextBeginningOfFrame) {
780                         Q_ASSERT(pf == f);
781                     } else if (priv->buffer().at(frag->stringPosition) == QTextEndOfFrame) {
782                         Q_ASSERT(pf != f);
783                         cf = pf;
784                         cb = 0;
785                         goto end;
786                     }
787                 }
788             }
789         }
790         cb = map.previous(cb);
791     }
792  end:
793     return *this;
794 }
795 
796 /*!
797     \class QTextBlockUserData
798     \reentrant
799 
800     \brief The QTextBlockUserData class is used to associate custom data with blocks of text.
801     \since 4.1
802 
803     \ingroup richtext-processing
804 
805     QTextBlockUserData provides an abstract interface for container classes that are used
806     to associate application-specific user data with text blocks in a QTextDocument.
807 
808     Generally, subclasses of this class provide functions to allow data to be stored
809     and retrieved, and instances are attached to blocks of text using
810     QTextBlock::setUserData(). This makes it possible to store additional data per text
811     block in a way that can be retrieved safely by the application.
812 
813     Each subclass should provide a reimplementation of the destructor to ensure that any
814     private data is automatically cleaned up when user data objects are deleted.
815 
816     \sa QTextBlock
817 */
818 
819 /*!
820     Destroys the user data.
821 */
~QTextBlockUserData()822 QTextBlockUserData::~QTextBlockUserData()
823 {
824 }
825 
826 /*!
827     \class QTextBlock
828     \reentrant
829 
830     \brief The QTextBlock class provides a container for text fragments in a
831     QTextDocument.
832 
833     \ingroup richtext-processing
834 
835     A text block encapsulates a block or paragraph of text in a QTextDocument.
836     QTextBlock provides read-only access to the block/paragraph structure of
837     QTextDocuments. It is mainly of use if you want to implement your own
838     layouts for the visual representation of a QTextDocument, or if you want to
839     iterate over a document and write out the contents in your own custom
840     format.
841 
842     Text blocks are created by their parent documents. If you need to create
843     a new text block, or modify the contents of a document while examining its
844     contents, use the cursor-based interface provided by QTextCursor instead.
845 
846     Each text block is located at a specific position() in a document().
847     The contents of the block can be obtained by using the text() function.
848     The length() function determines the block's size within the document
849     (including formatting characters).
850     The visual properties of the block are determined by its text layout(),
851     its charFormat(), and its blockFormat().
852 
853     The next() and previous() functions enable iteration over consecutive
854     valid blocks in a document under the condition that the document is not
855     modified by other means during the iteration process. Note that, although
856     blocks are returned in sequence, adjacent blocks may come from different
857     places in the document structure. The validity of a block can be determined
858     by calling isValid().
859 
860     QTextBlock provides comparison operators to make it easier to work with
861     blocks: \l operator==() compares two block for equality, \l operator!=()
862     compares two blocks for inequality, and \l operator<() determines whether
863     a block precedes another in the same document.
864 
865     \img qtextblock-sequence.png
866 
867     \sa QTextBlockFormat QTextCharFormat QTextFragment
868  */
869 
870 /*!
871     \fn QTextBlock::QTextBlock(QTextDocumentPrivate *priv, int b)
872 
873     \internal
874 */
875 
876 /*!
877     \fn QTextBlock::QTextBlock()
878 
879     \internal
880 */
881 
882 /*!
883     \fn QTextBlock::QTextBlock(const QTextBlock &other)
884 
885     Copies the \a other text block's attributes to this text block.
886 */
887 
888 /*!
889     \fn bool QTextBlock::isValid() const
890 
891     Returns true if this text block is valid; otherwise returns false.
892 */
893 
894 /*!
895     \fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
896 
897     Assigns the \a other text block to this text block.
898 */
899 
900 /*!
901     \fn bool QTextBlock::operator==(const QTextBlock &other) const
902 
903     Returns true if this text block is the same as the \a other text
904     block.
905 */
906 
907 /*!
908     \fn bool QTextBlock::operator!=(const QTextBlock &other) const
909 
910     Returns true if this text block is different from the \a other
911     text block.
912 */
913 
914 /*!
915     \fn bool QTextBlock::operator<(const QTextBlock &other) const
916 
917     Returns true if this text block occurs before the \a other text
918     block in the document.
919 */
920 
921 /*!
922     \class QTextBlock::iterator
923     \reentrant
924 
925     \brief The QTextBlock::iterator class provides an iterator for reading
926     the contents of a QTextBlock.
927 
928     \ingroup richtext-processing
929 
930     A block consists of a sequence of text fragments. This class provides
931     a way to iterate over these, and read their contents. It does not provide
932     a way to modify the internal structure or contents of the block.
933 
934     An iterator can be constructed and used to access the fragments within
935     a text block in the following way:
936 
937     \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 4
938     \snippet doc/src/snippets/textblock-fragments/xmlwriter.cpp 7
939 
940     \sa QTextFragment
941 */
942 
943 /*!
944     \typedef QTextBlock::Iterator
945 
946     Qt-style synonym for QTextBlock::iterator.
947 */
948 
949 /*!
950     \fn QTextBlock::iterator::iterator()
951 
952     Constructs an iterator for this text block.
953 */
954 
955 /*!
956     \fn QTextBlock::iterator::iterator(const iterator &other)
957 
958     Copy constructor. Constructs a copy of the \a other iterator.
959 */
960 
961 /*!
962     \fn bool QTextBlock::iterator::atEnd() const
963 
964     Returns true if the current item is the last item in the text block.
965 */
966 
967 /*!
968     \fn bool QTextBlock::iterator::operator==(const iterator &other) const
969 
970     Retuns true if this iterator is the same as the \a other iterator;
971     otherwise returns false.
972 */
973 
974 /*!
975     \fn bool QTextBlock::iterator::operator!=(const iterator &other) const
976 
977     Retuns true if this iterator is different from the \a other iterator;
978     otherwise returns false.
979 */
980 
981 /*!
982     \fn QTextBlock::iterator QTextBlock::iterator::operator++(int)
983 
984     The postfix ++ operator (\c{i++}) advances the iterator to the
985     next item in the text block and returns an iterator to the old current
986     item.
987 */
988 
989 /*!
990     \fn QTextBlock::iterator QTextBlock::iterator::operator--(int)
991 
992     The postfix -- operator (\c{i--}) makes the preceding item current and
993     returns an iterator to the old current item.
994 */
995 
996 /*!
997     \fn QTextDocumentPrivate *QTextBlock::docHandle() const
998 
999     \internal
1000 */
1001 
1002 /*!
1003     \fn int QTextBlock::fragmentIndex() const
1004 
1005     \internal
1006 */
1007 
1008 /*!
1009     Returns the index of the block's first character within the document.
1010  */
position() const1011 int QTextBlock::position() const
1012 {
1013     if (!p || !n)
1014         return 0;
1015 
1016     return p->blockMap().position(n);
1017 }
1018 
1019 /*!
1020     Returns the length of the block in characters.
1021 
1022     \note The length returned includes all formatting characters,
1023     for example, newline.
1024 
1025     \sa text() charFormat() blockFormat()
1026  */
length() const1027 int QTextBlock::length() const
1028 {
1029     if (!p || !n)
1030         return 0;
1031 
1032     return p->blockMap().size(n);
1033 }
1034 
1035 /*!
1036     Returns true if the given \a position is located within the text
1037     block; otherwise returns false.
1038  */
contains(int position) const1039 bool QTextBlock::contains(int position) const
1040 {
1041     if (!p || !n)
1042         return false;
1043 
1044     int pos = p->blockMap().position(n);
1045     int len = p->blockMap().size(n);
1046     return position >= pos && position < pos + len;
1047 }
1048 
1049 /*!
1050     Returns the QTextLayout that is used to lay out and display the
1051     block's contents.
1052 
1053     Note that the returned QTextLayout object can only be modified from the
1054     documentChanged implementation of a QAbstractTextDocumentLayout subclass.
1055     Any changes applied from the outside cause undefined behavior.
1056 
1057     \sa clearLayout()
1058  */
layout() const1059 QTextLayout *QTextBlock::layout() const
1060 {
1061     if (!p || !n)
1062         return 0;
1063 
1064     const QTextBlockData *b = p->blockMap().fragment(n);
1065     if (!b->layout)
1066         b->layout = new QTextLayout(*this);
1067     return b->layout;
1068 }
1069 
1070 /*!
1071     \since 4.4
1072     Clears the QTextLayout that is used to lay out and display the
1073     block's contents.
1074 
1075     \sa layout()
1076  */
clearLayout()1077 void QTextBlock::clearLayout()
1078 {
1079     if (!p || !n)
1080         return;
1081 
1082     const QTextBlockData *b = p->blockMap().fragment(n);
1083     if (b->layout)
1084         b->layout->clearLayout();
1085 }
1086 
1087 /*!
1088     Returns the QTextBlockFormat that describes block-specific properties.
1089 
1090     \sa charFormat()
1091  */
blockFormat() const1092 QTextBlockFormat QTextBlock::blockFormat() const
1093 {
1094     if (!p || !n)
1095         return QTextFormat().toBlockFormat();
1096 
1097     return p->formatCollection()->blockFormat(p->blockMap().fragment(n)->format);
1098 }
1099 
1100 /*!
1101     Returns an index into the document's internal list of block formats
1102     for the text block's format.
1103 
1104     \sa QTextDocument::allFormats()
1105 */
blockFormatIndex() const1106 int QTextBlock::blockFormatIndex() const
1107 {
1108     if (!p || !n)
1109         return -1;
1110 
1111     return p->blockMap().fragment(n)->format;
1112 }
1113 
1114 /*!
1115     Returns the QTextCharFormat that describes the block's character
1116     format. The block's character format is used when inserting text into
1117     an empty block.
1118 
1119     \sa blockFormat()
1120  */
charFormat() const1121 QTextCharFormat QTextBlock::charFormat() const
1122 {
1123     if (!p || !n)
1124         return QTextFormat().toCharFormat();
1125 
1126     return p->formatCollection()->charFormat(charFormatIndex());
1127 }
1128 
1129 /*!
1130     Returns an index into the document's internal list of character formats
1131     for the text block's character format.
1132 
1133     \sa QTextDocument::allFormats()
1134 */
charFormatIndex() const1135 int QTextBlock::charFormatIndex() const
1136 {
1137     if (!p || !n)
1138         return -1;
1139 
1140     return p->blockCharFormatIndex(n);
1141 }
1142 
1143 /*!
1144   \since 4.7
1145 
1146   Returns the resolved text direction.
1147 
1148   If the block has no explicit direction set, it will resolve the
1149   direction from the blocks content. Returns either Qt::LeftToRight
1150   or Qt::RightToLeft.
1151 
1152   \sa QTextFormat::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection
1153 */
textDirection() const1154 Qt::LayoutDirection QTextBlock::textDirection() const
1155 {
1156     Qt::LayoutDirection dir = blockFormat().layoutDirection();
1157     if (dir != Qt::LayoutDirectionAuto)
1158         return dir;
1159 
1160     dir = p->defaultTextOption.textDirection();
1161     if (dir != Qt::LayoutDirectionAuto)
1162         return dir;
1163 
1164     const QString buffer = p->buffer();
1165 
1166     const int pos = position();
1167     QTextDocumentPrivate::FragmentIterator it = p->find(pos);
1168     QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
1169     for (; it != end; ++it) {
1170         const QTextFragmentData * const frag = it.value();
1171         const QChar *p = buffer.constData() + frag->stringPosition;
1172         const QChar * const end = p + frag->size_array[0];
1173         while (p < end) {
1174             switch(QChar::direction(p->unicode()))
1175             {
1176             case QChar::DirL:
1177                 return Qt::LeftToRight;
1178             case QChar::DirR:
1179             case QChar::DirAL:
1180                 return Qt::RightToLeft;
1181             default:
1182                 break;
1183             }
1184             ++p;
1185         }
1186     }
1187     return Qt::LeftToRight;
1188 }
1189 
1190 /*!
1191     Returns the block's contents as plain text.
1192 
1193     \sa length() charFormat() blockFormat()
1194  */
text() const1195 QString QTextBlock::text() const
1196 {
1197     if (!p || !n)
1198         return QString();
1199 
1200     const QString buffer = p->buffer();
1201     QString text;
1202     text.reserve(length());
1203 
1204     const int pos = position();
1205     QTextDocumentPrivate::FragmentIterator it = p->find(pos);
1206     QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char
1207     for (; it != end; ++it) {
1208         const QTextFragmentData * const frag = it.value();
1209         text += QString::fromRawData(buffer.constData() + frag->stringPosition, frag->size_array[0]);
1210     }
1211 
1212     return text;
1213 }
1214 
1215 
1216 /*!
1217     Returns the text document this text block belongs to, or 0 if the
1218     text block does not belong to any document.
1219 */
document() const1220 const QTextDocument *QTextBlock::document() const
1221 {
1222     return p ? p->document() : 0;
1223 }
1224 
1225 /*!
1226     If the block represents a list item, returns the list that the item belongs
1227     to; otherwise returns 0.
1228 */
textList() const1229 QTextList *QTextBlock::textList() const
1230 {
1231     if (!isValid())
1232         return 0;
1233 
1234     const QTextBlockFormat fmt = blockFormat();
1235     QTextObject *obj = p->document()->objectForFormat(fmt);
1236     return qobject_cast<QTextList *>(obj);
1237 }
1238 
1239 /*!
1240     \since 4.1
1241 
1242     Returns a pointer to a QTextBlockUserData object if previously set with
1243     setUserData() or a null pointer.
1244 */
userData() const1245 QTextBlockUserData *QTextBlock::userData() const
1246 {
1247     if (!p || !n)
1248         return 0;
1249 
1250     const QTextBlockData *b = p->blockMap().fragment(n);
1251     return b->userData;
1252 }
1253 
1254 /*!
1255     \since 4.1
1256 
1257     Attaches the given \a data object to the text block.
1258 
1259     QTextBlockUserData can be used to store custom settings.  The
1260     ownership is passed to the underlying text document, i.e. the
1261     provided QTextBlockUserData object will be deleted if the
1262     corresponding text block gets deleted. The user data object is
1263     not stored in the undo history, so it will not be available after
1264     undoing the deletion of a text block.
1265 
1266     For example, if you write a programming editor in an IDE, you may
1267     want to let your user set breakpoints visually in your code for an
1268     integrated debugger. In a programming editor a line of text
1269     usually corresponds to one QTextBlock. The QTextBlockUserData
1270     interface allows the developer to store data for each QTextBlock,
1271     like for example in which lines of the source code the user has a
1272     breakpoint set. Of course this could also be stored externally,
1273     but by storing it inside the QTextDocument, it will for example be
1274     automatically deleted when the user deletes the associated
1275     line. It's really just a way to store custom information in the
1276     QTextDocument without using custom properties in QTextFormat which
1277     would affect the undo/redo stack.
1278 */
setUserData(QTextBlockUserData * data)1279 void QTextBlock::setUserData(QTextBlockUserData *data)
1280 {
1281     if (!p || !n)
1282         return;
1283 
1284     const QTextBlockData *b = p->blockMap().fragment(n);
1285     if (data != b->userData)
1286         delete b->userData;
1287     b->userData = data;
1288 }
1289 
1290 /*!
1291     \since 4.1
1292 
1293     Returns the integer value previously set with setUserState() or -1.
1294 */
userState() const1295 int QTextBlock::userState() const
1296 {
1297     if (!p || !n)
1298         return -1;
1299 
1300     const QTextBlockData *b = p->blockMap().fragment(n);
1301     return b->userState;
1302 }
1303 
1304 /*!
1305     \since 4.1
1306 
1307     Stores the specified \a state integer value in the text block. This may be
1308     useful for example in a syntax highlighter to store a text parsing state.
1309 */
setUserState(int state)1310 void QTextBlock::setUserState(int state)
1311 {
1312     if (!p || !n)
1313         return;
1314 
1315     const QTextBlockData *b = p->blockMap().fragment(n);
1316     b->userState = state;
1317 }
1318 
1319 /*!
1320     \since 4.4
1321 
1322     Returns the blocks revision.
1323 
1324     \sa setRevision(), QTextDocument::revision()
1325 */
revision() const1326 int QTextBlock::revision() const
1327 {
1328     if (!p || !n)
1329         return -1;
1330 
1331     const QTextBlockData *b = p->blockMap().fragment(n);
1332     return b->revision;
1333 }
1334 
1335 /*!
1336     \since 4.4
1337 
1338     Sets a blocks revision to \a rev.
1339 
1340     \sa revision(), QTextDocument::revision()
1341 */
setRevision(int rev)1342 void QTextBlock::setRevision(int rev)
1343 {
1344     if (!p || !n)
1345         return;
1346 
1347     const QTextBlockData *b = p->blockMap().fragment(n);
1348     b->revision = rev;
1349 }
1350 
1351 /*!
1352     \since 4.4
1353 
1354     Returns true if the block is visible; otherwise returns false.
1355 
1356     \sa setVisible()
1357 */
isVisible() const1358 bool QTextBlock::isVisible() const
1359 {
1360     if (!p || !n)
1361         return true;
1362 
1363     const QTextBlockData *b = p->blockMap().fragment(n);
1364     return !b->hidden;
1365 }
1366 
1367 /*!
1368     \since 4.4
1369 
1370     Sets the block's visibility to \a visible.
1371 
1372     \sa isVisible()
1373 */
setVisible(bool visible)1374 void QTextBlock::setVisible(bool visible)
1375 {
1376     if (!p || !n)
1377         return;
1378 
1379     const QTextBlockData *b = p->blockMap().fragment(n);
1380     b->hidden = !visible;
1381 }
1382 
1383 
1384 /*!
1385 \since 4.4
1386 
1387     Returns the number of this block, or -1 if the block is invalid.
1388 
1389     \sa QTextCursor::blockNumber()
1390 
1391 */
blockNumber() const1392 int QTextBlock::blockNumber() const
1393 {
1394     if (!p || !n)
1395         return -1;
1396     return p->blockMap().position(n, 1);
1397 }
1398 
1399 /*!
1400 \since 4.5
1401 
1402     Returns the first line number of this block, or -1 if the block is invalid.
1403     Unless the layout supports it, the line number is identical to the block number.
1404 
1405     \sa QTextBlock::blockNumber()
1406 
1407 */
firstLineNumber() const1408 int QTextBlock::firstLineNumber() const
1409 {
1410     if (!p || !n)
1411         return -1;
1412     return p->blockMap().position(n, 2);
1413 }
1414 
1415 
1416 /*!
1417 \since 4.5
1418 
1419 Sets the line count to \a count.
1420 
1421 \sa lineCount()
1422 */
setLineCount(int count)1423 void QTextBlock::setLineCount(int count)
1424 {
1425     if (!p || !n)
1426         return;
1427     p->blockMap().setSize(n, count, 2);
1428 }
1429 /*!
1430 \since 4.5
1431 
1432 Returns the line count. Not all document layouts support this feature.
1433 
1434 \sa setLineCount()
1435  */
lineCount() const1436 int QTextBlock::lineCount() const
1437 {
1438     if (!p || !n)
1439         return -1;
1440     return p->blockMap().size(n, 2);
1441 }
1442 
1443 
1444 /*!
1445     Returns a text block iterator pointing to the beginning of the
1446     text block.
1447 
1448     \sa end()
1449 */
begin() const1450 QTextBlock::iterator QTextBlock::begin() const
1451 {
1452     if (!p || !n)
1453         return iterator();
1454 
1455     int pos = position();
1456     int len = length() - 1; // exclude the fragment that holds the paragraph separator
1457     int b = p->fragmentMap().findNode(pos);
1458     int e = p->fragmentMap().findNode(pos+len);
1459     return iterator(p, b, e, b);
1460 }
1461 
1462 /*!
1463     Returns a text block iterator pointing to the end of the text
1464     block.
1465 
1466     \sa begin() next() previous()
1467 */
end() const1468 QTextBlock::iterator QTextBlock::end() const
1469 {
1470     if (!p || !n)
1471         return iterator();
1472 
1473     int pos = position();
1474     int len = length() - 1; // exclude the fragment that holds the paragraph separator
1475     int b = p->fragmentMap().findNode(pos);
1476     int e = p->fragmentMap().findNode(pos+len);
1477     return iterator(p, b, e, e);
1478 }
1479 
1480 
1481 /*!
1482     Returns the text block in the document after this block, or an empty
1483     text block if this is the last one.
1484 
1485     Note that the next block may be in a different frame or table to this block.
1486 
1487     \sa previous() begin() end()
1488 */
next() const1489 QTextBlock QTextBlock::next() const
1490 {
1491     if (!isValid() || !p->blockMap().isValid(n))
1492         return QTextBlock();
1493 
1494     return QTextBlock(p, p->blockMap().next(n));
1495 }
1496 
1497 /*!
1498     Returns the text block in the document before this block, or an empty text
1499     block if this is the first one.
1500 
1501     Note that the next block may be in a different frame or table to this block.
1502 
1503     \sa next() begin() end()
1504 */
previous() const1505 QTextBlock QTextBlock::previous() const
1506 {
1507     if (!p)
1508         return QTextBlock();
1509 
1510     return QTextBlock(p, p->blockMap().previous(n));
1511 }
1512 
1513 
1514 /*!
1515     Returns the text fragment the iterator currently points to.
1516 */
fragment() const1517 QTextFragment QTextBlock::iterator::fragment() const
1518 {
1519     int ne = n;
1520     int formatIndex = p->fragmentMap().fragment(n)->format;
1521     do {
1522         ne = p->fragmentMap().next(ne);
1523     } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
1524     return QTextFragment(p, n, ne);
1525 }
1526 
1527 /*!
1528     The prefix ++ operator (\c{++i}) advances the iterator to the
1529     next item in the hash and returns an iterator to the new current
1530     item.
1531 */
1532 
operator ++()1533 QTextBlock::iterator &QTextBlock::iterator::operator++()
1534 {
1535     int ne = n;
1536     int formatIndex = p->fragmentMap().fragment(n)->format;
1537     do {
1538         ne = p->fragmentMap().next(ne);
1539     } while (ne != e && p->fragmentMap().fragment(ne)->format == formatIndex);
1540     n = ne;
1541     return *this;
1542 }
1543 
1544 /*!
1545     The prefix -- operator (\c{--i}) makes the preceding item
1546     current and returns an iterator pointing to the new current item.
1547 */
1548 
operator --()1549 QTextBlock::iterator &QTextBlock::iterator::operator--()
1550 {
1551     n = p->fragmentMap().previous(n);
1552 
1553     if (n == b)
1554         return *this;
1555 
1556     int formatIndex = p->fragmentMap().fragment(n)->format;
1557     int last = n;
1558 
1559     while (n != b && p->fragmentMap().fragment(n)->format != formatIndex) {
1560         last = n;
1561         n = p->fragmentMap().previous(n);
1562     }
1563 
1564     n = last;
1565     return *this;
1566 }
1567 
1568 
1569 /*!
1570     \class QTextFragment
1571     \reentrant
1572 
1573     \brief The QTextFragment class holds a piece of text in a
1574     QTextDocument with a single QTextCharFormat.
1575 
1576     \ingroup richtext-processing
1577 
1578     A text fragment describes a piece of text that is stored with a single
1579     character format. Text in which the character format changes can be
1580     represented by sequences of text fragments with different formats.
1581 
1582     If the user edits the text in a fragment and introduces a different
1583     character format, the fragment's text will be split at each point where
1584     the format changes, and new fragments will be created.
1585     For example, changing the style of some text in the middle of a
1586     sentence will cause the fragment to be broken into three separate fragments:
1587     the first and third with the same format as before, and the second with
1588     the new style. The first fragment will contain the text from the beginning
1589     of the sentence, the second will contain the text from the middle, and the
1590     third takes the text from the end of the sentence.
1591 
1592     \img qtextfragment-split.png
1593 
1594     A fragment's text and character format can be obtained with the text()
1595     and charFormat() functions. The length() function gives the length of
1596     the text in the fragment. position() gives the position in the document
1597     of the start of the fragment. To determine whether the fragment contains
1598     a particular position within the document, use the contains() function.
1599 
1600     \sa QTextDocument, {Rich Text Document Structure}
1601 */
1602 
1603 /*!
1604     \fn QTextFragment::QTextFragment(const QTextDocumentPrivate *priv, int f, int fe)
1605     \internal
1606 */
1607 
1608 /*!
1609     \fn QTextFragment::QTextFragment()
1610 
1611     Creates a new empty text fragment.
1612 */
1613 
1614 /*!
1615     \fn QTextFragment::QTextFragment(const QTextFragment &other)
1616 
1617     Copies the content (text and format) of the \a other text fragment
1618     to this text fragment.
1619 */
1620 
1621 /*!
1622     \fn QTextFragment &QTextFragment::operator=(const QTextFragment
1623     &other)
1624 
1625     Assigns the content (text and format) of the \a other text fragment
1626     to this text fragment.
1627 */
1628 
1629 /*!
1630     \fn bool QTextFragment::isValid() const
1631 
1632     Returns true if this is a valid text fragment (i.e. has a valid
1633     position in a document); otherwise returns false.
1634 */
1635 
1636 /*!
1637     \fn bool QTextFragment::operator==(const QTextFragment &other) const
1638 
1639     Returns true if this text fragment is the same (at the same
1640     position) as the \a other text fragment; otherwise returns false.
1641 */
1642 
1643 /*!
1644     \fn bool QTextFragment::operator!=(const QTextFragment &other) const
1645 
1646     Returns true if this text fragment is different (at a different
1647     position) from the \a other text fragment; otherwise returns
1648     false.
1649 */
1650 
1651 /*!
1652     \fn bool QTextFragment::operator<(const QTextFragment &other) const
1653 
1654     Returns true if this text fragment appears earlier in the document
1655     than the \a other text fragment; otherwise returns false.
1656 */
1657 
1658 /*!
1659     Returns the glyphs of this text fragment. The positions of the glyphs are
1660     relative to the position of the QTextBlock's layout.
1661 
1662     \sa QGlyphRun, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphRun()
1663 */
1664 #if !defined(QT_NO_RAWFONT)
glyphRuns() const1665 QList<QGlyphRun> QTextFragment::glyphRuns() const
1666 {
1667     if (!p || !n)
1668         return QList<QGlyphRun>();
1669 
1670     int pos = position();
1671     int len = length();
1672     if (len == 0)
1673         return QList<QGlyphRun>();
1674 
1675     int blockNode = p->blockMap().findNode(pos);
1676 
1677     const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
1678     QTextLayout *layout = blockData->layout;
1679 
1680     QList<QGlyphRun> ret;
1681     for (int i=0; i<layout->lineCount(); ++i) {
1682         QTextLine textLine = layout->lineAt(i);
1683         ret += textLine.glyphs(pos, len);
1684     }
1685 
1686     return ret;
1687 }
1688 #endif // QT_NO_RAWFONT
1689 
1690 /*!
1691     Returns the position of this text fragment in the document.
1692 */
position() const1693 int QTextFragment::position() const
1694 {
1695     if (!p || !n)
1696         return 0; // ### -1 instead?
1697 
1698     return p->fragmentMap().position(n);
1699 }
1700 
1701 /*!
1702     Returns the number of characters in the text fragment.
1703 
1704     \sa text()
1705 */
length() const1706 int QTextFragment::length() const
1707 {
1708     if (!p || !n)
1709         return 0;
1710 
1711     int len = 0;
1712     int f = n;
1713     while (f != ne) {
1714         len += p->fragmentMap().size(f);
1715         f = p->fragmentMap().next(f);
1716     }
1717     return len;
1718 }
1719 
1720 /*!
1721     Returns true if the text fragment contains the text at the given
1722     \a position in the document; otherwise returns false.
1723 */
contains(int position) const1724 bool QTextFragment::contains(int position) const
1725 {
1726     if (!p || !n)
1727         return false;
1728     int pos = this->position();
1729     return position >= pos && position < pos + length();
1730 }
1731 
1732 /*!
1733     Returns the text fragment's character format.
1734 
1735     \sa text()
1736 */
charFormat() const1737 QTextCharFormat QTextFragment::charFormat() const
1738 {
1739     if (!p || !n)
1740         return QTextCharFormat();
1741     const QTextFragmentData *data = p->fragmentMap().fragment(n);
1742     return p->formatCollection()->charFormat(data->format);
1743 }
1744 
1745 /*!
1746     Returns an index into the document's internal list of character formats
1747     for the text fragment's character format.
1748 
1749     \sa QTextDocument::allFormats()
1750 */
charFormatIndex() const1751 int QTextFragment::charFormatIndex() const
1752 {
1753     if (!p || !n)
1754         return -1;
1755     const QTextFragmentData *data = p->fragmentMap().fragment(n);
1756     return data->format;
1757 }
1758 
1759 /*!
1760     Returns the text fragment's as plain text.
1761 
1762     \sa length(), charFormat()
1763 */
text() const1764 QString QTextFragment::text() const
1765 {
1766     if (!p || !n)
1767         return QString();
1768 
1769     QString result;
1770     QString buffer = p->buffer();
1771     int f = n;
1772     while (f != ne) {
1773         const QTextFragmentData * const frag = p->fragmentMap().fragment(f);
1774         result += QString(buffer.constData() + frag->stringPosition, frag->size_array[0]);
1775         f = p->fragmentMap().next(f);
1776     }
1777     return result;
1778 }
1779 
1780 QT_END_NAMESPACE
1781