1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#include "qtextobject.h"
43
#include "qtextobject_p.h"
44
#include "qtextdocument.h"
45
#include "qtextformat_p.h"
46
#include "qtextdocument_p.h"
47
#include "qtextcursor.h"
48
#include "qtextlist.h"
49
#include "qabstracttextdocumentlayout.h"
50
#include "qtextengine_p.h"
51
#include "qdebug.h"
52
53
QT_BEGIN_NAMESPACE
54
55
// ### DOC: We ought to explain the CONCEPT of objectIndexes if
56
// relevant to the public API
57
/*!
58
    \class QTextObject
59
    \reentrant
60
61
    \brief The QTextObject class is a base class for different kinds
62
    of objects that can group parts of a QTextDocument together.
63
64
    \ingroup richtext-processing
65
66
    The common grouping text objects are lists (QTextList), frames
67
    (QTextFrame), and tables (QTextTable). A text object has an
68
    associated format() and document().
69
70
    There are essentially two kinds of text objects: those that are used
71
    with blocks (block formats), and those that are used with characters
72
    (character formats). The first kind are derived from QTextBlockGroup,
73
    and the second kind from QTextFrame.
74
75
    You rarely need to use this class directly. When creating custom text
76
    objects, you will also need to reimplement QTextDocument::createObject()
77
    which acts as a factory method for creating text objects.
78
79
    \sa QTextDocument, {Text Object Example}
80
*/
81
82
/*!
83
    \fn QTextObject::QTextObject(QTextDocument *document)
84
85
    Creates a new QTextObject for the given \a document.
86
87
    \warning This function should never be called directly, but only
88
    from QTextDocument::createObject().
89
*/
90
QTextObject::QTextObject(QTextDocument *doc)
91
    : QObject(*new QTextObjectPrivate(doc), doc)
92
{
93
}
94
95
/*!
96
  \fn QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *document)
97
98
  \internal
99
*/
100
QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *doc)
101
    : QObject(p, doc)
102
{
103
}
104
105
/*!
106
    Destroys the text object.
107
108
    \warning Text objects are owned by the document, so you should
109
    never destroy them yourself.
110
*/
111
QTextObject::~QTextObject()
112
{
113
}
114
115
/*!
116
    Returns the text object's format.
117
118
    \sa setFormat() document()
119
*/
120
QTextFormat QTextObject::format() const
121
{
122
    Q_D(const QTextObject);
123
    return d->pieceTable->formatCollection()->objectFormat(d->objectIndex);
124
}
125
126
/*!
127
    Returns the index of the object's format in the document's internal
128
    list of formats.
129
130
    \sa QTextDocument::allFormats()
131
*/
132
int QTextObject::formatIndex() const
133
{
134
    Q_D(const QTextObject);
135
    return d->pieceTable->formatCollection()->objectFormatIndex(d->objectIndex);
136
}
137
138
139
/*!
140
    Sets the text object's \a format.
141
142
    \sa format()
143
*/
144
void QTextObject::setFormat(const QTextFormat &format)
145
{
146
    Q_D(QTextObject);
147
    int idx = d->pieceTable->formatCollection()->indexForFormat(format);
148
    d->pieceTable->changeObjectFormat(this, idx);
149
}
150
151
/*!
152
    Returns the object index of this object. This can be used together with
153
    QTextFormat::setObjectIndex().
154
*/
155
int QTextObject::objectIndex() const
156
{
157
    Q_D(const QTextObject);
158
    return d->objectIndex;
159
}
160
161
/*!
162
    Returns the document this object belongs to.
163
164
    \sa format()
165
*/
166
QTextDocument *QTextObject::document() const
167
{
168
    return static_cast<QTextDocument *>(parent());
169
}
170
171
/*!
172
  \internal
173
*/
174
QTextDocumentPrivate *QTextObject::docHandle() const
175
{
176
    return static_cast<const QTextDocument *>(parent())->docHandle();
177
}
178
179
/*!
180
    \class QTextBlockGroup
181
    \reentrant
182
183
    \brief The QTextBlockGroup class provides a container for text blocks within
184
    a QTextDocument.
185
186
    \ingroup richtext-processing
187
188
    Block groups can be used to organize blocks of text within a document.
189
    They maintain an up-to-date list of the text blocks that belong to
190
    them, even when text blocks are being edited.
191
192
    Each group has a parent document which is specified when the group is
193
    constructed.
194
195
    Text blocks can be inserted into a group with blockInserted(), and removed
196
    with blockRemoved(). If a block's format is changed, blockFormatChanged()
197
    is called.
198
199
    The list of blocks in the group is returned by blockList(). Note that the
200
    blocks in the list are not necessarily adjacent elements in the document;
201
    for example, the top-level items in a multi-level list will be separated
202
    by the items in lower levels of the list.
203
204
    \sa QTextBlock QTextDocument
205
*/
206
207
void QTextBlockGroupPrivate::markBlocksDirty()
208
{
209
    for (int i = 0; i < blocks.count(); ++i) {
210
        const QTextBlock &block = blocks.at(i);
211
        pieceTable->documentChange(block.position(), block.length());
212
    }
213
}
214
215
/*!
216
    \fn QTextBlockGroup::QTextBlockGroup(QTextDocument *document)
217
218
    Creates a new new block group for the given \a document.
219
220
    \warning This function should only be called from
221
    QTextDocument::createObject().
222
*/
223
QTextBlockGroup::QTextBlockGroup(QTextDocument *doc)
224
    : QTextObject(*new QTextBlockGroupPrivate(doc), doc)
225
{
226
}
227
228
/*!
229
  \internal
230
*/
231
QTextBlockGroup::QTextBlockGroup(QTextBlockGroupPrivate &p, QTextDocument *doc)
232
    : QTextObject(p, doc)
233
{
234
}
235
236
/*!
237
    Destroys this block group; the blocks are not deleted, they simply
238
    don't belong to this block anymore.
239
*/
240
QTextBlockGroup::~QTextBlockGroup()
241
{
242
}
243
244
// ### DOC: Shouldn't this be insertBlock()?
245
/*!
246
    Appends the given \a block to the end of the group.
247
248
    \warning If you reimplement this function you must call the base
249
    class implementation.
250
*/
251
void QTextBlockGroup::blockInserted(const QTextBlock &block)
252
{
253
    Q_D(QTextBlockGroup);
254
    QTextBlockGroupPrivate::BlockList::Iterator it = qLowerBound(d->blocks.begin(), d->blocks.end(), block);
255
    d->blocks.insert(it, block);
256
    d->markBlocksDirty();
257
}
258
259
// ### DOC: Shouldn't this be removeBlock()?
260
/*!
261
    Removes the given \a block from the group; the block itself is not
262
    deleted, it simply isn't a member of this group anymore.
263
*/
264
void QTextBlockGroup::blockRemoved(const QTextBlock &block)
265
{
266
    Q_D(QTextBlockGroup);
267
    d->blocks.removeAll(block);
268
    d->markBlocksDirty();
269
    if (d->blocks.isEmpty()) {
270
        document()->docHandle()->deleteObject(this);
271
        return;
272
    }
273
}
274
275
/*!
276
    This function is called whenever the specified \a block of text is changed.
277
    The text block is a member of this group.
278
279
    The base class implementation does nothing.
280
*/
281
void QTextBlockGroup::blockFormatChanged(const QTextBlock &)
282
{
283
}
284
285
/*!
286
    Returns a (possibly empty) list of all the blocks that are part of
287
    the block group.
288
*/
289
QList<QTextBlock> QTextBlockGroup::blockList() const
290
{
291
    Q_D(const QTextBlockGroup);
292
    return d->blocks;
293
}
294
295
296
297
QTextFrameLayoutData::~QTextFrameLayoutData()
298
{
299
}
300
301
302
/*!
303
    \class QTextFrame
304
    \reentrant
305
306
    \brief The QTextFrame class represents a frame in a QTextDocument.
307
308
    \ingroup richtext-processing
309
310
    Text frames provide structure for the text in a document. They are used
311
    as generic containers for other document elements.
312
    Frames are usually created by using QTextCursor::insertFrame().
313
314
    \omit
315
    Each frame in a document consists of a frame start character,
316
    QChar(0xFDD0), followed by the frame's contents, followed by a
317
    frame end character, QChar(0xFDD1). The character formats of the
318
    start and end character contain a reference to the frame object's
319
    objectIndex.
320
    \endomit
321
322
    Frames can be used to create hierarchical structures in rich text documents.
323
    Each document has a root frame (QTextDocument::rootFrame()), and each frame
324
    beneath the root frame has a parent frame and a (possibly empty) list of
325
    child frames. The parent frame can be found with parentFrame(), and the
326
    childFrames() function provides a list of child frames.
327
328
    Each frame contains at least one text block to enable text cursors to
329
    insert new document elements within. As a result, the QTextFrame::iterator
330
    class is used to traverse both the blocks and child frames within a given
331
    frame. The first and last child elements in the frame can be found with
332
    begin() and end().
333
334
    A frame also has a format (specified using QTextFrameFormat) which can be set
335
    with setFormat() and read with format().
336
337
    Text cursors can be obtained that point to the first and last valid cursor
338
    positions within a frame; use the firstCursorPosition() and
339
    lastCursorPosition() functions for this. The frame's extent in the
340
    document can be found with firstPosition() and lastPosition().
341
342
    You can iterate over a frame's contents using the
343
    QTextFrame::iterator class: this provides read-only access to its
344
    internal list of text blocks and child frames.
345
346
    \sa QTextCursor QTextDocument
347
*/
348
349
/*!
350
    \typedef QTextFrame::Iterator
351
352
    Qt-style synonym for QTextFrame::iterator.
353
*/
354
355
/*!
356
    \fn QTextFrame *QTextFrame::iterator::parentFrame() const
357
358
    Returns the parent frame of the current frame.
359
360
    \sa currentFrame() QTextFrame::parentFrame()
361
*/
362
363
/*!
364
    \fn bool QTextFrame::iterator::operator==(const iterator &other) const
365
366
    Retuns true if the iterator is the same as the \a other iterator;
367
    otherwise returns false.
368
*/
369
370
/*!
371
    \fn bool QTextFrame::iterator::operator!=(const iterator &other) const
372
373
    Retuns true if the iterator is different from the \a other iterator;
374
    otherwise returns false.
375
*/
376
377
/*!
378
    \fn QTextFrame::iterator QTextFrame::iterator::operator++(int)
379
380
    The postfix ++ operator (\c{i++}) advances the iterator to the
381
    next item in the text frame, and returns an iterator to the old item.
382
*/
383
384
/*!
385
    \fn QTextFrame::iterator QTextFrame::iterator::operator--(int)
386
387
    The postfix -- operator (\c{i--}) makes the preceding item in the
388
    current frame, and returns an iterator to the old item.
389
*/
390
391
/*!
392
    \fn void QTextFrame::setFrameFormat(const QTextFrameFormat &format)
393
394
    Sets the frame's \a format.
395
396
    \sa frameFormat()
397
*/
398
399
/*!
400
    \fn QTextFrameFormat QTextFrame::frameFormat() const
401
402
    Returns the frame's format.
403
404
    \sa setFrameFormat()
405
*/
406
407
/*!
408
    \fn QTextFrame::QTextFrame(QTextDocument *document)
409
410
    Creates a new empty frame for the text \a document.
411
*/
412
QTextFrame::QTextFrame(QTextDocument *doc)
413
    : QTextObject(*new QTextFramePrivate(doc), doc)
414
{
415
}
416
417
// ### DOC: What does this do to child frames?
418
/*!
419
    Destroys the frame, and removes it from the document's layout.
420
*/
421
QTextFrame::~QTextFrame()
422
{
423
    Q_D(QTextFrame);
424
    delete d->layoutData;
425
}
426
427
/*!
428
    \internal
429
*/
430
QTextFrame::QTextFrame(QTextFramePrivate &p, QTextDocument *doc)
431
    : QTextObject(p, doc)
432
{
433
}
434
435
/*!
436
    Returns a (possibly empty) list of the frame's child frames.
437
438
    \sa parentFrame()
439
*/
440
QList<QTextFrame *> QTextFrame::childFrames() const
441
{
442
    Q_D(const QTextFrame);
443
    return d->childFrames;
444
}
445
446
/*!
447
    Returns the frame's parent frame. If the frame is the root frame of a
448
    document, this will return 0.
449
450
    \sa childFrames() QTextDocument::rootFrame()
451
*/
452
QTextFrame *QTextFrame::parentFrame() const
453
{
454
    Q_D(const QTextFrame);
455
    return d->parentFrame;
456
}
457
458
459
/*!
460
    Returns the first cursor position inside the frame.
461
462
    \sa lastCursorPosition() firstPosition() lastPosition()
463
*/
464
QTextCursor QTextFrame::firstCursorPosition() const
465
{
466
    Q_D(const QTextFrame);
467
    return QTextCursor(d->pieceTable, firstPosition());
468
}
469
470
/*!
471
    Returns the last cursor position inside the frame.
472
473
    \sa firstCursorPosition() firstPosition() lastPosition()
474
*/
475
QTextCursor QTextFrame::lastCursorPosition() const
476
{
477
    Q_D(const QTextFrame);
478
    return QTextCursor(d->pieceTable, lastPosition());
479
}
480
481
/*!
482
    Returns the first document position inside the frame.
483
484
    \sa lastPosition() firstCursorPosition() lastCursorPosition()
485
*/
486
int QTextFrame::firstPosition() const
487
{
488
    Q_D(const QTextFrame);
489
    if (!d->fragment_start)
490
        return 0;
491
    return d->pieceTable->fragmentMap().position(d->fragment_start) + 1;
492
}
493
494
/*!
495
    Returns the last document position inside the frame.
496
497
    \sa firstPosition() firstCursorPosition() lastCursorPosition()
498
*/
499
int QTextFrame::lastPosition() const
500
{
501
    Q_D(const QTextFrame);
502
    if (!d->fragment_end)
503
        return d->pieceTable->length() - 1;
504
    return d->pieceTable->fragmentMap().position(d->fragment_end);
505
}
506
507
/*!
508
  \internal
509
*/
510
QTextFrameLayoutData *QTextFrame::layoutData() const
511
{
512
    Q_D(const QTextFrame);
513
    return d->layoutData;
514
}
515
516
/*!
517
  \internal
518
*/
519
void QTextFrame::setLayoutData(QTextFrameLayoutData *data)
520
{
521
    Q_D(QTextFrame);
522
    delete d->layoutData;
523
    d->layoutData = data;
524
}
525
526
527
528
void QTextFramePrivate::fragmentAdded(const QChar &type, uint fragment)
529
{
530
    if (type == QTextBeginningOfFrame) {
531
        Q_ASSERT(!fragment_start);
532
        fragment_start = fragment;
533
    } else if (type == QTextEndOfFrame) {
534
        Q_ASSERT(!fragment_end);
535
        fragment_end = fragment;
536
    } else if (type == QChar::ObjectReplacementCharacter) {
537
        Q_ASSERT(!fragment_start);
538
        Q_ASSERT(!fragment_end);
539
        fragment_start = fragment;
540
        fragment_end = fragment;
541
    } else {
542
        Q_ASSERT(false);
543
    }
544
}
545
546
void QTextFramePrivate::fragmentRemoved(const QChar &type, uint fragment)
547
{
548
    Q_UNUSED(fragment); // --release warning
549
    if (type == QTextBeginningOfFrame) {
550
        Q_ASSERT(fragment_start == fragment);
551
        fragment_start = 0;
552
    } else if (type == QTextEndOfFrame) {
553
        Q_ASSERT(fragment_end == fragment);
554
        fragment_end = 0;
555
    } else if (type == QChar::ObjectReplacementCharacter) {
556
        Q_ASSERT(fragment_start == fragment);
557
        Q_ASSERT(fragment_end == fragment);
558
        fragment_start = 0;
559
        fragment_end = 0;
560
    } else {
561
        Q_ASSERT(false);
562
    }
563
    remove_me();
564
}
565
566
567
void QTextFramePrivate::remove_me()
568
{
569
    Q_Q(QTextFrame);
570
    if (fragment_start == 0 && fragment_end == 0
571
        && !parentFrame) {
572
        q->document()->docHandle()->deleteObject(q);
573
        return;
574
    }
575
576
    if (!parentFrame)
577
        return;
578
579
    int index = parentFrame->d_func()->childFrames.indexOf(q);
580
581
    // iterator over all children and move them to the parent
582
    for (int i = 0; i < childFrames.size(); ++i) {
583
        QTextFrame *c = childFrames.at(i);
584
        parentFrame->d_func()->childFrames.insert(index, c);
585
        c->d_func()->parentFrame = parentFrame;
586
        ++index;
587
    }
588
    Q_ASSERT(parentFrame->d_func()->childFrames.at(index) == q);
589
    parentFrame->d_func()->childFrames.removeAt(index);
590
591
    childFrames.clear();
592
    parentFrame = 0;
593
}
594
595
/*!
596
    \class QTextFrame::iterator
597
    \reentrant
598
599
    \brief The iterator class provides an iterator for reading
600
    the contents of a QTextFrame.
601
602
    \ingroup richtext-processing
603
604
    A frame consists of an arbitrary sequence of \l{QTextBlock}s and
605
    child \l{QTextFrame}s. This class provides a way to iterate over the
606
    child objects of a frame, and read their contents. It does not provide
607
    a way to modify the contents of the frame.
608
609
*/
610
611
/*!
612
    \fn bool QTextFrame::iterator::atEnd() const
613
614
    Returns true if the current item is the last item in the text frame.
615
*/
616
617
/*!
618
    Returns an iterator pointing to the first document element inside the frame.
619
    Please see the document \l{STL-style-Iterators} for more information.
620
621
    \sa end()
622
*/
623
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
*/
636
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
*/
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
*/
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
*/
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
*/
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
*/
700
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
*/
711
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
*/
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
*/
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
*/
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
 */
1011
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
 */
1027
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
 */
1039
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
 */
1059
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
 */
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
 */
1092
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
*/
1106
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
 */
1121
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
*/
1135
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
*/
1154
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
 */
1195
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
*/
1220
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
*/
1229
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
*/
1245
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
*/
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
*/
1295
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
*/
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
*/
1326
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
*/
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
*/
1358
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
*/
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
*/
1392
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
*/
1408
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
*/
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
 */
1436
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
*/
1450
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
*/
1468
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
*/
1489
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
*/
1505
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
*/
1517
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
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
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)
1665
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
*/
1693
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
*/
1706
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
*/
1724
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
*/
1737
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
*/
1751
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
*/
1764
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