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