Compile with clang when C++11 support is enabled
[profile/ivi/qtbase.git] / src / gui / text / qtextcursor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qtextcursor.h"
43 #include "qtextcursor_p.h"
44 #include "qglobal.h"
45 #include "qtextdocumentfragment.h"
46 #include "qtextdocumentfragment_p.h"
47 #include "qtextlist.h"
48 #include "qtexttable.h"
49 #include "qtexttable_p.h"
50 #include "qtextengine_p.h"
51 #include "qabstracttextdocumentlayout.h"
52
53 #include <qtextlayout.h>
54 #include <qdebug.h>
55
56 QT_BEGIN_NAMESPACE
57
58 enum {
59     AdjustPrev = 0x1,
60     AdjustUp = 0x3,
61     AdjustNext = 0x4,
62     AdjustDown = 0x12
63 };
64
65 QTextCursorPrivate::QTextCursorPrivate(QTextDocumentPrivate *p)
66     : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0),
67       currentCharFormat(-1), visualNavigation(false), keepPositionOnInsert(false),
68       changed(false)
69 {
70     priv->addCursor(this);
71 }
72
73 QTextCursorPrivate::QTextCursorPrivate(const QTextCursorPrivate &rhs)
74     : QSharedData(rhs)
75 {
76     position = rhs.position;
77     anchor = rhs.anchor;
78     adjusted_anchor = rhs.adjusted_anchor;
79     priv = rhs.priv;
80     x = rhs.x;
81     currentCharFormat = rhs.currentCharFormat;
82     visualNavigation = rhs.visualNavigation;
83     keepPositionOnInsert = rhs.keepPositionOnInsert;
84     changed = rhs.changed;
85     priv->addCursor(this);
86 }
87
88 QTextCursorPrivate::~QTextCursorPrivate()
89 {
90     if (priv)
91         priv->removeCursor(this);
92 }
93
94 QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int positionOfChange, int charsAddedOrRemoved, QTextUndoCommand::Operation op)
95 {
96     QTextCursorPrivate::AdjustResult result = QTextCursorPrivate::CursorMoved;
97     // not(!) <= , so that inserting text adjusts the cursor correctly
98     if (position < positionOfChange
99         || (position == positionOfChange
100             && (op == QTextUndoCommand::KeepCursor
101                 || keepPositionOnInsert)
102             )
103          ) {
104         result = CursorUnchanged;
105     } else {
106         if (charsAddedOrRemoved < 0 && position < positionOfChange - charsAddedOrRemoved)
107             position = positionOfChange;
108         else
109             position += charsAddedOrRemoved;
110
111         currentCharFormat = -1;
112     }
113
114     if (anchor >= positionOfChange
115         && (anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
116         if (charsAddedOrRemoved < 0 && anchor < positionOfChange - charsAddedOrRemoved)
117             anchor = positionOfChange;
118         else
119             anchor += charsAddedOrRemoved;
120     }
121
122     if (adjusted_anchor >= positionOfChange
123         && (adjusted_anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {
124         if (charsAddedOrRemoved < 0 && adjusted_anchor < positionOfChange - charsAddedOrRemoved)
125             adjusted_anchor = positionOfChange;
126         else
127             adjusted_anchor += charsAddedOrRemoved;
128     }
129
130     return result;
131 }
132
133 void QTextCursorPrivate::setX()
134 {
135     if (priv->isInEditBlock()) {
136         x = -1; // mark dirty
137         return;
138     }
139
140     QTextBlock block = this->block();
141     const QTextLayout *layout = blockLayout(block);
142     int pos = position - block.position();
143
144     QTextLine line = layout->lineForTextPosition(pos);
145     if (line.isValid())
146         x = line.cursorToX(pos);
147     else
148         x = -1; // delayed init.  Makes movePosition() call setX later on again.
149 }
150
151 void QTextCursorPrivate::remove()
152 {
153     if (anchor == position)
154         return;
155     currentCharFormat = -1;
156     int pos1 = position;
157     int pos2 = adjusted_anchor;
158     QTextUndoCommand::Operation op = QTextUndoCommand::KeepCursor;
159     if (pos1 > pos2) {
160         pos1 = adjusted_anchor;
161         pos2 = position;
162         op = QTextUndoCommand::MoveCursor;
163     }
164
165     // deleting inside table? -> delete only content
166     QTextTable *table = complexSelectionTable();
167     if (table) {
168         priv->beginEditBlock();
169         int startRow, startCol, numRows, numCols;
170         selectedTableCells(&startRow, &numRows, &startCol, &numCols);
171         clearCells(table, startRow, startCol, numRows, numCols, op);
172         adjusted_anchor = anchor = position;
173         priv->endEditBlock();
174     } else {
175         priv->remove(pos1, pos2-pos1, op);
176         adjusted_anchor = anchor = position;
177         priv->finishEdit();
178     }
179
180 }
181
182 void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
183 {
184     priv->beginEditBlock();
185
186     for (int row = startRow; row < startRow + numRows; ++row)
187         for (int col = startCol; col < startCol + numCols; ++col) {
188             QTextTableCell cell = table->cellAt(row, col);
189             const int startPos = cell.firstPosition();
190             const int endPos = cell.lastPosition();
191             Q_ASSERT(startPos <= endPos);
192             priv->remove(startPos, endPos - startPos, op);
193         }
194
195     priv->endEditBlock();
196 }
197
198 bool QTextCursorPrivate::canDelete(int pos) const
199 {
200     QTextDocumentPrivate::FragmentIterator fit = priv->find(pos);
201     QTextCharFormat fmt = priv->formatCollection()->charFormat((*fit)->format);
202     return (fmt.objectIndex() == -1 || fmt.objectType() == QTextFormat::ImageObject);
203 }
204
205 void QTextCursorPrivate::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
206 {
207     QTextFormatCollection *formats = priv->formatCollection();
208     int idx = formats->indexForFormat(format);
209     Q_ASSERT(formats->format(idx).isBlockFormat());
210
211     priv->insertBlock(position, idx, formats->indexForFormat(charFormat));
212     currentCharFormat = -1;
213 }
214
215 void QTextCursorPrivate::adjustCursor(QTextCursor::MoveOperation m)
216 {
217     adjusted_anchor = anchor;
218     if (position == anchor)
219         return;
220
221     QTextFrame *f_position = priv->frameAt(position);
222     QTextFrame *f_anchor = priv->frameAt(adjusted_anchor);
223
224     if (f_position != f_anchor) {
225         // find common parent frame
226         QList<QTextFrame *> positionChain;
227         QList<QTextFrame *> anchorChain;
228         QTextFrame *f = f_position;
229         while (f) {
230             positionChain.prepend(f);
231             f = f->parentFrame();
232         }
233         f = f_anchor;
234         while (f) {
235             anchorChain.prepend(f);
236             f = f->parentFrame();
237         }
238         Q_ASSERT(positionChain.at(0) == anchorChain.at(0));
239         int i = 1;
240         int l = qMin(positionChain.size(), anchorChain.size());
241         for (; i < l; ++i) {
242             if (positionChain.at(i) != anchorChain.at(i))
243                 break;
244         }
245
246         if (m <= QTextCursor::WordLeft) {
247             if (i < positionChain.size())
248                 position = positionChain.at(i)->firstPosition() - 1;
249         } else {
250             if (i < positionChain.size())
251                 position = positionChain.at(i)->lastPosition() + 1;
252         }
253         if (position < adjusted_anchor) {
254             if (i < anchorChain.size())
255                 adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;
256         } else {
257             if (i < anchorChain.size())
258                 adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;
259         }
260
261         f_position = positionChain.at(i-1);
262     }
263
264     // same frame, either need to adjust to cell boundaries or return
265     QTextTable *table = qobject_cast<QTextTable *>(f_position);
266     if (!table)
267         return;
268
269     QTextTableCell c_position = table->cellAt(position);
270     QTextTableCell c_anchor = table->cellAt(adjusted_anchor);
271     if (c_position != c_anchor) {
272         position = c_position.firstPosition();
273         if (position < adjusted_anchor)
274             adjusted_anchor = c_anchor.lastPosition();
275         else
276             adjusted_anchor = c_anchor.firstPosition();
277     }
278     currentCharFormat = -1;
279 }
280
281 void QTextCursorPrivate::aboutToRemoveCell(int from, int to)
282 {
283     Q_ASSERT(from <= to);
284     if (position == anchor)
285         return;
286
287     QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
288     if (!t)
289         return;
290     QTextTableCell removedCellFrom = t->cellAt(from);
291     QTextTableCell removedCellEnd = t->cellAt(to);
292     if (! removedCellFrom.isValid() || !removedCellEnd.isValid())
293         return;
294
295     int curFrom = position;
296     int curTo = adjusted_anchor;
297     if (curTo < curFrom)
298         qSwap(curFrom, curTo);
299
300     QTextTableCell cellStart = t->cellAt(curFrom);
301     QTextTableCell cellEnd = t->cellAt(curTo);
302
303     if (cellStart.row() >= removedCellFrom.row() && cellEnd.row() <= removedCellEnd.row()
304             && cellStart.column() >= removedCellFrom.column()
305               && cellEnd.column() <= removedCellEnd.column()) { // selection is completely removed
306         // find a new position, as close as possible to where we were.
307         QTextTableCell cell;
308         if (removedCellFrom.row() == 0 && removedCellEnd.row() == t->rows()-1) // removed n columns
309             cell = t->cellAt(cellStart.row(), removedCellEnd.column()+1);
310         else if (removedCellFrom.column() == 0 && removedCellEnd.column() == t->columns()-1) // removed n rows
311             cell = t->cellAt(removedCellEnd.row() + 1, cellStart.column());
312
313         int newPosition;
314         if (cell.isValid())
315             newPosition = cell.firstPosition();
316         else
317             newPosition = t->lastPosition()+1;
318
319         setPosition(newPosition);
320         anchor = newPosition;
321         adjusted_anchor = newPosition;
322         x = 0;
323     }
324     else if (cellStart.row() >= removedCellFrom.row() && cellStart.row() <= removedCellEnd.row()
325         && cellEnd.row() > removedCellEnd.row()) {
326         int newPosition = t->cellAt(removedCellEnd.row() + 1, cellStart.column()).firstPosition();
327         if (position < anchor)
328             position = newPosition;
329         else
330             anchor = adjusted_anchor = newPosition;
331     }
332     else if (cellStart.column() >= removedCellFrom.column() && cellStart.column() <= removedCellEnd.column()
333         && cellEnd.column() > removedCellEnd.column()) {
334         int newPosition = t->cellAt(cellStart.row(), removedCellEnd.column()+1).firstPosition();
335         if (position < anchor)
336             position = newPosition;
337         else
338             anchor = adjusted_anchor = newPosition;
339     }
340 }
341
342 bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode)
343 {
344     currentCharFormat = -1;
345     bool adjustX = true;
346     QTextBlock blockIt = block();
347     bool visualMovement = priv->defaultCursorMoveStyle == Qt::VisualMoveStyle;
348
349     if (!blockIt.isValid())
350         return false;
351
352     if (blockIt.textDirection() == Qt::RightToLeft) {
353         if (op == QTextCursor::WordLeft)
354             op = QTextCursor::NextWord;
355         else if (op == QTextCursor::WordRight)
356             op = QTextCursor::PreviousWord;
357
358         if (!visualMovement) {
359             if (op == QTextCursor::Left)
360                 op = QTextCursor::NextCharacter;
361             else if (op == QTextCursor::Right)
362                 op = QTextCursor::PreviousCharacter;
363         }
364     }
365
366     const QTextLayout *layout = blockLayout(blockIt);
367     int relativePos = position - blockIt.position();
368     QTextLine line;
369     if (!priv->isInEditBlock())
370         line = layout->lineForTextPosition(relativePos);
371
372     Q_ASSERT(priv->frameAt(position) == priv->frameAt(adjusted_anchor));
373
374     int newPosition = position;
375
376     if (mode == QTextCursor::KeepAnchor && complexSelectionTable() != 0) {
377         if ((op >= QTextCursor::EndOfLine && op <= QTextCursor::NextWord)
378                 || (op >= QTextCursor::Right && op <= QTextCursor::WordRight)) {
379             QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
380             Q_ASSERT(t); // as we have already made sure we have a complex selection
381             QTextTableCell cell_pos = t->cellAt(position);
382             if (cell_pos.column() + cell_pos.columnSpan() != t->columns())
383                 op = QTextCursor::NextCell;
384         }
385     }
386
387     if (x == -1 && !priv->isInEditBlock() && (op == QTextCursor::Up || op == QTextCursor::Down))
388         setX();
389
390     switch(op) {
391     case QTextCursor::NoMove:
392         return true;
393
394     case QTextCursor::Start:
395         newPosition = 0;
396         break;
397     case QTextCursor::StartOfLine: {
398         newPosition = blockIt.position();
399         if (line.isValid())
400             newPosition += line.textStart();
401
402         break;
403     }
404     case QTextCursor::StartOfBlock: {
405         newPosition = blockIt.position();
406         break;
407     }
408     case QTextCursor::PreviousBlock: {
409         if (blockIt == priv->blocksBegin())
410             return false;
411         blockIt = blockIt.previous();
412
413         newPosition = blockIt.position();
414         break;
415     }
416     case QTextCursor::PreviousCharacter:
417         if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
418             newPosition = qMin(position, adjusted_anchor);
419         else
420             newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
421         break;
422     case QTextCursor::Left:
423         if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
424             newPosition = visualMovement ? qMax(position, adjusted_anchor)
425                                          : qMin(position, adjusted_anchor);
426         else
427             newPosition = visualMovement ? priv->leftCursorPosition(position)
428                                          : priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
429         break;
430     case QTextCursor::StartOfWord: {
431         if (relativePos == 0)
432             break;
433
434         // skip if already at word start
435         QTextEngine *engine = layout->engine();
436         engine->attributes();
437         if ((relativePos == blockIt.length() - 1)
438             && (engine->atSpace(relativePos - 1) || engine->atWordSeparator(relativePos - 1)))
439             return false;
440
441         if (relativePos < blockIt.length()-1)
442             ++position;
443
444         // FALL THROUGH!
445     }
446     case QTextCursor::PreviousWord:
447     case QTextCursor::WordLeft:
448         newPosition = priv->previousCursorPosition(position, QTextLayout::SkipWords);
449         break;
450     case QTextCursor::Up: {
451         int i = line.lineNumber() - 1;
452         if (i == -1) {
453             if (blockIt == priv->blocksBegin())
454                 return false;
455             int blockPosition = blockIt.position();
456             QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
457             if (table) {
458                 QTextTableCell cell = table->cellAt(blockPosition);
459                 if (cell.firstPosition() == blockPosition) {
460                     int row = cell.row() - 1;
461                     if (row >= 0) {
462                         blockPosition = table->cellAt(row, cell.column()).lastPosition();
463                     } else {
464                         // move to line above the table
465                         blockPosition = table->firstPosition() - 1;
466                     }
467                     blockIt = priv->blocksFind(blockPosition);
468                 } else {
469                     blockIt = blockIt.previous();
470                 }
471             } else {
472                 blockIt = blockIt.previous();
473             }
474             layout = blockLayout(blockIt);
475             i = layout->lineCount()-1;
476         }
477         if (layout->lineCount()) {
478             QTextLine line = layout->lineAt(i);
479             newPosition = line.xToCursor(x) + blockIt.position();
480         } else {
481             newPosition = blockIt.position();
482         }
483         adjustX = false;
484         break;
485     }
486
487     case QTextCursor::End:
488         newPosition = priv->length() - 1;
489         break;
490     case QTextCursor::EndOfLine: {
491         if (!line.isValid() || line.textLength() == 0) {
492             if (blockIt.length() >= 1)
493                 // position right before the block separator
494                 newPosition = blockIt.position() + blockIt.length() - 1;
495             break;
496         }
497         newPosition = blockIt.position() + line.textStart() + line.textLength();
498         if (newPosition >= priv->length())
499             newPosition = priv->length() - 1;
500         if (line.lineNumber() < layout->lineCount() - 1) {
501             const QString text = blockIt.text();
502             // ###### this relies on spaces being the cause for linebreaks.
503             // this doesn't work with japanese
504             if (text.at(line.textStart() + line.textLength() - 1).isSpace())
505                 --newPosition;
506         }
507         break;
508     }
509     case QTextCursor::EndOfWord: {
510         QTextEngine *engine = layout->engine();
511         engine->attributes();
512         const int len = blockIt.length() - 1;
513         if (relativePos >= len)
514             return false;
515         if (engine->atWordSeparator(relativePos)) {
516             ++relativePos;
517             while (relativePos < len && engine->atWordSeparator(relativePos))
518                 ++relativePos;
519         } else {
520             while (relativePos < len && !engine->atSpace(relativePos) && !engine->atWordSeparator(relativePos))
521                 ++relativePos;
522         }
523         newPosition = blockIt.position() + relativePos;
524         break;
525     }
526     case QTextCursor::EndOfBlock:
527         if (blockIt.length() >= 1)
528             // position right before the block separator
529             newPosition = blockIt.position() + blockIt.length() - 1;
530         break;
531     case QTextCursor::NextBlock: {
532         blockIt = blockIt.next();
533         if (!blockIt.isValid())
534             return false;
535
536         newPosition = blockIt.position();
537         break;
538     }
539     case QTextCursor::NextCharacter:
540         if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
541             newPosition = qMax(position, adjusted_anchor);
542         else
543             newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
544         break;
545     case QTextCursor::Right:
546         if (mode == QTextCursor::MoveAnchor && position != adjusted_anchor)
547             newPosition = visualMovement ? qMin(position, adjusted_anchor)
548                                          : qMax(position, adjusted_anchor);
549         else
550             newPosition = visualMovement ? priv->rightCursorPosition(position)
551                                          : priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
552         break;
553     case QTextCursor::NextWord:
554     case QTextCursor::WordRight:
555         newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);
556         break;
557
558     case QTextCursor::Down: {
559         int i = line.lineNumber() + 1;
560
561         if (i >= layout->lineCount()) {
562             int blockPosition = blockIt.position() + blockIt.length() - 1;
563             QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));
564             if (table) {
565                 QTextTableCell cell = table->cellAt(blockPosition);
566                 if (cell.lastPosition() == blockPosition) {
567                     int row = cell.row() + cell.rowSpan();
568                     if (row < table->rows()) {
569                         blockPosition = table->cellAt(row, cell.column()).firstPosition();
570                     } else {
571                         // move to line below the table
572                         blockPosition = table->lastPosition() + 1;
573                     }
574                     blockIt = priv->blocksFind(blockPosition);
575                 } else {
576                     blockIt = blockIt.next();
577                 }
578             } else {
579                 blockIt = blockIt.next();
580             }
581
582             if (blockIt == priv->blocksEnd())
583                 return false;
584             layout = blockLayout(blockIt);
585             i = 0;
586         }
587         if (layout->lineCount()) {
588             QTextLine line = layout->lineAt(i);
589             newPosition = line.xToCursor(x) + blockIt.position();
590         } else {
591             newPosition = blockIt.position();
592         }
593         adjustX = false;
594         break;
595     }
596     case QTextCursor::NextCell: // fall through
597     case QTextCursor::PreviousCell: // fall through
598     case QTextCursor::NextRow: // fall through
599     case QTextCursor::PreviousRow: {
600         QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
601         if (!table)
602             return false;
603
604         QTextTableCell cell = table->cellAt(position);
605         Q_ASSERT(cell.isValid());
606         int column = cell.column();
607         int row = cell.row();
608         const int currentRow = row;
609         if (op == QTextCursor::NextCell || op == QTextCursor::NextRow) {
610             do {
611                 column += cell.columnSpan();
612                 if (column >= table->columns()) {
613                     column = 0;
614                     ++row;
615                 }
616                 cell = table->cellAt(row, column);
617                 // note we also continue while we have not reached a cell thats not merged with one above us
618             } while (cell.isValid()
619                     && ((op == QTextCursor::NextRow && currentRow == cell.row())
620                         || cell.row() < row));
621         }
622         else if (op == QTextCursor::PreviousCell || op == QTextCursor::PreviousRow) {
623             do {
624                 --column;
625                 if (column < 0) {
626                     column = table->columns()-1;
627                     --row;
628                 }
629                 cell = table->cellAt(row, column);
630                 // note we also continue while we have not reached a cell thats not merged with one above us
631             } while (cell.isValid()
632                     && ((op == QTextCursor::PreviousRow && currentRow == cell.row())
633                         || cell.row() < row));
634         }
635         if (cell.isValid())
636             newPosition = cell.firstPosition();
637         break;
638     }
639     }
640
641     if (mode == QTextCursor::KeepAnchor) {
642         QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(position));
643         if (table && ((op >= QTextCursor::PreviousBlock && op <= QTextCursor::WordLeft)
644                       || (op >= QTextCursor::NextBlock && op <= QTextCursor::WordRight))) {
645             int oldColumn = table->cellAt(position).column();
646
647             const QTextTableCell otherCell = table->cellAt(newPosition);
648             if (!otherCell.isValid())
649                 return false;
650
651             int newColumn = otherCell.column();
652             if ((oldColumn > newColumn && op >= QTextCursor::End)
653                 || (oldColumn < newColumn && op <= QTextCursor::WordLeft))
654                 return false;
655         }
656     }
657
658     const bool moved = setPosition(newPosition);
659
660     if (mode == QTextCursor::MoveAnchor) {
661         anchor = position;
662         adjusted_anchor = position;
663     } else {
664         adjustCursor(op);
665     }
666
667     if (adjustX)
668         setX();
669
670     return moved;
671 }
672
673 QTextTable *QTextCursorPrivate::complexSelectionTable() const
674 {
675     if (position == anchor)
676         return 0;
677
678     QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
679     if (t) {
680         QTextTableCell cell_pos = t->cellAt(position);
681         QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
682
683         Q_ASSERT(cell_anchor.isValid());
684
685         if (cell_pos == cell_anchor)
686             t = 0;
687     }
688     return t;
689 }
690
691 void QTextCursorPrivate::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
692 {
693     *firstRow = -1;
694     *firstColumn = -1;
695     *numRows = -1;
696     *numColumns = -1;
697
698     if (position == anchor)
699         return;
700
701     QTextTable *t = qobject_cast<QTextTable *>(priv->frameAt(position));
702     if (!t)
703         return;
704
705     QTextTableCell cell_pos = t->cellAt(position);
706     QTextTableCell cell_anchor = t->cellAt(adjusted_anchor);
707
708     Q_ASSERT(cell_anchor.isValid());
709
710     if (cell_pos == cell_anchor)
711         return;
712
713     *firstRow = qMin(cell_pos.row(), cell_anchor.row());
714     *firstColumn = qMin(cell_pos.column(), cell_anchor.column());
715     *numRows = qMax(cell_pos.row() + cell_pos.rowSpan(), cell_anchor.row() + cell_anchor.rowSpan()) - *firstRow;
716     *numColumns = qMax(cell_pos.column() + cell_pos.columnSpan(), cell_anchor.column() + cell_anchor.columnSpan()) - *firstColumn;
717 }
718
719 static void setBlockCharFormatHelper(QTextDocumentPrivate *priv, int pos1, int pos2,
720                                const QTextCharFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
721 {
722     QTextBlock it = priv->blocksFind(pos1);
723     QTextBlock end = priv->blocksFind(pos2);
724     if (end.isValid())
725         end = end.next();
726
727     for (; it != end; it = it.next()) {
728         priv->setCharFormat(it.position() - 1, 1, format, changeMode);
729     }
730 }
731
732 void QTextCursorPrivate::setBlockCharFormat(const QTextCharFormat &_format,
733     QTextDocumentPrivate::FormatChangeMode changeMode)
734 {
735     priv->beginEditBlock();
736
737     QTextCharFormat format = _format;
738     format.clearProperty(QTextFormat::ObjectIndex);
739
740     QTextTable *table = complexSelectionTable();
741     if (table) {
742         int row_start, col_start, num_rows, num_cols;
743         selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
744
745         Q_ASSERT(row_start != -1);
746         for (int r = row_start; r < row_start + num_rows; ++r) {
747             for (int c = col_start; c < col_start + num_cols; ++c) {
748                 QTextTableCell cell = table->cellAt(r, c);
749                 int rspan = cell.rowSpan();
750                 int cspan = cell.columnSpan();
751                 if (rspan != 1) {
752                     int cr = cell.row();
753                     if (cr != r)
754                         continue;
755                 }
756                 if (cspan != 1) {
757                     int cc = cell.column();
758                     if (cc != c)
759                         continue;
760                 }
761
762                 int pos1 = cell.firstPosition();
763                 int pos2 = cell.lastPosition();
764                 setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
765             }
766         }
767     } else {
768         int pos1 = position;
769         int pos2 = adjusted_anchor;
770         if (pos1 > pos2) {
771             pos1 = adjusted_anchor;
772             pos2 = position;
773         }
774
775         setBlockCharFormatHelper(priv, pos1, pos2, format, changeMode);
776     }
777     priv->endEditBlock();
778 }
779
780
781 void QTextCursorPrivate::setBlockFormat(const QTextBlockFormat &format, QTextDocumentPrivate::FormatChangeMode changeMode)
782 {
783     QTextTable *table = complexSelectionTable();
784     if (table) {
785         priv->beginEditBlock();
786         int row_start, col_start, num_rows, num_cols;
787         selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
788
789         Q_ASSERT(row_start != -1);
790         for (int r = row_start; r < row_start + num_rows; ++r) {
791             for (int c = col_start; c < col_start + num_cols; ++c) {
792                 QTextTableCell cell = table->cellAt(r, c);
793                 int rspan = cell.rowSpan();
794                 int cspan = cell.columnSpan();
795                 if (rspan != 1) {
796                     int cr = cell.row();
797                     if (cr != r)
798                         continue;
799                 }
800                 if (cspan != 1) {
801                     int cc = cell.column();
802                     if (cc != c)
803                         continue;
804                 }
805
806                 int pos1 = cell.firstPosition();
807                 int pos2 = cell.lastPosition();
808                 priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
809             }
810         }
811         priv->endEditBlock();
812     } else {
813         int pos1 = position;
814         int pos2 = adjusted_anchor;
815         if (pos1 > pos2) {
816             pos1 = adjusted_anchor;
817             pos2 = position;
818         }
819
820         priv->setBlockFormat(priv->blocksFind(pos1), priv->blocksFind(pos2), format, changeMode);
821     }
822 }
823
824 void QTextCursorPrivate::setCharFormat(const QTextCharFormat &_format, QTextDocumentPrivate::FormatChangeMode changeMode)
825 {
826     Q_ASSERT(position != anchor);
827
828     QTextCharFormat format = _format;
829     format.clearProperty(QTextFormat::ObjectIndex);
830
831     QTextTable *table = complexSelectionTable();
832     if (table) {
833         priv->beginEditBlock();
834         int row_start, col_start, num_rows, num_cols;
835         selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
836
837         Q_ASSERT(row_start != -1);
838         for (int r = row_start; r < row_start + num_rows; ++r) {
839             for (int c = col_start; c < col_start + num_cols; ++c) {
840                 QTextTableCell cell = table->cellAt(r, c);
841                 int rspan = cell.rowSpan();
842                 int cspan = cell.columnSpan();
843                 if (rspan != 1) {
844                     int cr = cell.row();
845                     if (cr != r)
846                         continue;
847                 }
848                 if (cspan != 1) {
849                     int cc = cell.column();
850                     if (cc != c)
851                         continue;
852                 }
853
854                 int pos1 = cell.firstPosition();
855                 int pos2 = cell.lastPosition();
856                 priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
857             }
858         }
859         priv->endEditBlock();
860     } else {
861         int pos1 = position;
862         int pos2 = adjusted_anchor;
863         if (pos1 > pos2) {
864             pos1 = adjusted_anchor;
865             pos2 = position;
866         }
867
868         priv->setCharFormat(pos1, pos2-pos1, format, changeMode);
869     }
870 }
871
872
873 QTextLayout *QTextCursorPrivate::blockLayout(QTextBlock &block) const{
874     QTextLayout *tl = block.layout();
875     if (!tl->lineCount() && priv->layout())
876         priv->layout()->blockBoundingRect(block);
877     return tl;
878 }
879
880 /*!
881     \class QTextCursor
882     \reentrant
883
884     \brief The QTextCursor class offers an API to access and modify QTextDocuments.
885
886     \ingroup richtext-processing
887     \ingroup shared
888
889     Text cursors are objects that are used to access and modify the
890     contents and underlying structure of text documents via a
891     programming interface that mimics the behavior of a cursor in a
892     text editor. QTextCursor contains information about both the
893     cursor's position within a QTextDocument and any selection that it
894     has made.
895
896     QTextCursor is modeled on the way a text cursor behaves in a text
897     editor, providing a programmatic means of performing standard
898     actions through the user interface. A document can be thought of
899     as a single string of characters. The cursor's current position()
900     then is always either \e between two consecutive characters in the
901     string, or else \e before the very first character or \e after the
902     very last character in the string.  Documents can also contain
903     tables, lists, images, and other objects in addition to text but,
904     from the developer's point of view, the document can be treated as
905     one long string.  Some portions of that string can be considered
906     to lie within particular blocks (e.g. paragraphs), or within a
907     table's cell, or a list's item, or other structural elements. When
908     we refer to "current character" we mean the character immediately
909     \e before the cursor position() in the document. Similarly, the
910     "current block" is the block that contains the cursor position().
911
912     A QTextCursor also has an anchor() position. The text that is
913     between the anchor() and the position() is the selection. If
914     anchor() == position() there is no selection.
915
916     The cursor position can be changed programmatically using
917     setPosition() and movePosition(); the latter can also be used to
918     select text. For selections see selectionStart(), selectionEnd(),
919     hasSelection(), clearSelection(), and removeSelectedText().
920
921     If the position() is at the start of a block atBlockStart()
922     returns true; and if it is at the end of a block atBlockEnd() returns
923     true. The format of the current character is returned by
924     charFormat(), and the format of the current block is returned by
925     blockFormat().
926
927     Formatting can be applied to the current text document using the
928     setCharFormat(), mergeCharFormat(), setBlockFormat() and
929     mergeBlockFormat() functions. The 'set' functions will replace the
930     cursor's current character or block format, while the 'merge'
931     functions add the given format properties to the cursor's current
932     format. If the cursor has a selection the given format is applied
933     to the current selection. Note that when only parts of a block is
934     selected the block format is applied to the entire block. The text
935     at the current character position can be turned into a list using
936     createList().
937
938     Deletions can be achieved using deleteChar(),
939     deletePreviousChar(), and removeSelectedText().
940
941     Text strings can be inserted into the document with the insertText()
942     function, blocks (representing new paragraphs) can be inserted with
943     insertBlock().
944
945     Existing fragments of text can be inserted with insertFragment() but,
946     if you want to insert pieces of text in various formats, it is usually
947     still easier to use insertText() and supply a character format.
948
949     Various types of higher-level structure can also be inserted into the
950     document with the cursor:
951
952     \list
953     \li Lists are ordered sequences of block elements that are decorated with
954        bullet points or symbols. These are inserted in a specified format
955        with insertList().
956     \li Tables are inserted with the insertTable() function, and can be
957        given an optional format. These contain an array of cells that can
958        be traversed using the cursor.
959     \li Inline images are inserted with insertImage(). The image to be
960        used can be specified in an image format, or by name.
961     \li Frames are inserted by calling insertFrame() with a specified format.
962     \endlist
963
964     Actions can be grouped (i.e. treated as a single action for
965     undo/redo) using beginEditBlock() and endEditBlock().
966
967     Cursor movements are limited to valid cursor positions. In Latin
968     writing this is between any two consecutive characters in the
969     text, before the first character, or after the last character. In
970     some other writing systems cursor movements are limited to
971     "clusters" (e.g. a syllable in Devanagari, or a base letter plus
972     diacritics).  Functions such as movePosition() and deleteChar()
973     limit cursor movement to these valid positions.
974
975     \sa {Rich Text Processing}
976
977 */
978
979 /*!
980     \enum QTextCursor::MoveOperation
981
982     \value NoMove Keep the cursor where it is
983
984     \value Start Move to the start of the document.
985     \value StartOfLine Move to the start of the current line.
986     \value StartOfBlock Move to the start of the current block.
987     \value StartOfWord Move to the start of the current word.
988     \value PreviousBlock Move to the start of the previous block.
989     \value PreviousCharacter Move to the previous character.
990     \value PreviousWord Move to the beginning of the previous word.
991     \value Up Move up one line.
992     \value Left Move left one character.
993     \value WordLeft Move left one word.
994
995     \value End Move to the end of the document.
996     \value EndOfLine Move to the end of the current line.
997     \value EndOfWord Move to the end of the current word.
998     \value EndOfBlock Move to the end of the current block.
999     \value NextBlock Move to the beginning of the next block.
1000     \value NextCharacter Move to the next character.
1001     \value NextWord Move to the next word.
1002     \value Down Move down one line.
1003     \value Right Move right one character.
1004     \value WordRight Move right one word.
1005
1006     \value NextCell  Move to the beginning of the next table cell inside the
1007            current table. If the current cell is the last cell in the row, the
1008            cursor will move to the first cell in the next row.
1009     \value PreviousCell  Move to the beginning of the previous table cell
1010            inside the current table. If the current cell is the first cell in
1011            the row, the cursor will move to the last cell in the previous row.
1012     \value NextRow  Move to the first new cell of the next row in the current
1013            table.
1014     \value PreviousRow  Move to the last cell of the previous row in the
1015            current table.
1016
1017     \sa movePosition()
1018 */
1019
1020 /*!
1021     \enum QTextCursor::MoveMode
1022
1023     \value MoveAnchor Moves the anchor to the same position as the cursor itself.
1024     \value KeepAnchor Keeps the anchor where it is.
1025
1026     If the anchor() is kept where it is and the position() is moved,
1027     the text in between will be selected.
1028 */
1029
1030 /*!
1031     \enum QTextCursor::SelectionType
1032
1033     This enum describes the types of selection that can be applied with the
1034     select() function.
1035
1036     \value Document         Selects the entire document.
1037     \value BlockUnderCursor Selects the block of text under the cursor.
1038     \value LineUnderCursor  Selects the line of text under the cursor.
1039     \value WordUnderCursor  Selects the word under the cursor. If the cursor
1040            is not positioned within a string of selectable characters, no
1041            text is selected.
1042 */
1043
1044 /*!
1045     Constructs a null cursor.
1046  */
1047 QTextCursor::QTextCursor()
1048     : d(0)
1049 {
1050 }
1051
1052 /*!
1053     Constructs a cursor pointing to the beginning of the \a document.
1054  */
1055 QTextCursor::QTextCursor(QTextDocument *document)
1056     : d(new QTextCursorPrivate(document->docHandle()))
1057 {
1058 }
1059
1060 /*!
1061     Constructs a cursor pointing to the beginning of the \a frame.
1062 */
1063 QTextCursor::QTextCursor(QTextFrame *frame)
1064     : d(new QTextCursorPrivate(frame->document()->docHandle()))
1065 {
1066     d->adjusted_anchor = d->anchor = d->position = frame->firstPosition();
1067 }
1068
1069
1070 /*!
1071     Constructs a cursor pointing to the beginning of the \a block.
1072 */
1073 QTextCursor::QTextCursor(const QTextBlock &block)
1074     : d(new QTextCursorPrivate(block.docHandle()))
1075 {
1076     d->adjusted_anchor = d->anchor = d->position = block.position();
1077 }
1078
1079
1080 /*!
1081   \internal
1082  */
1083 QTextCursor::QTextCursor(QTextDocumentPrivate *p, int pos)
1084     : d(new QTextCursorPrivate(p))
1085 {
1086     d->adjusted_anchor = d->anchor = d->position = pos;
1087
1088     d->setX();
1089 }
1090
1091 /*!
1092     \internal
1093 */
1094 QTextCursor::QTextCursor(QTextCursorPrivate *d)
1095 {
1096     Q_ASSERT(d);
1097     this->d = d;
1098 }
1099
1100 /*!
1101     Constructs a new cursor that is a copy of \a cursor.
1102  */
1103 QTextCursor::QTextCursor(const QTextCursor &cursor)
1104 {
1105     d = cursor.d;
1106 }
1107
1108 /*!
1109     Makes a copy of \a cursor and assigns it to this QTextCursor. Note
1110     that QTextCursor is an \l{Implicitly Shared Classes}{implicitly
1111     shared} class.
1112
1113  */
1114 QTextCursor &QTextCursor::operator=(const QTextCursor &cursor)
1115 {
1116     d = cursor.d;
1117     return *this;
1118 }
1119
1120 /*!
1121     Destroys the QTextCursor.
1122  */
1123 QTextCursor::~QTextCursor()
1124 {
1125 }
1126
1127 /*!
1128     Returns true if the cursor is null; otherwise returns false. A null
1129     cursor is created by the default constructor.
1130  */
1131 bool QTextCursor::isNull() const
1132 {
1133     return !d || !d->priv;
1134 }
1135
1136 /*!
1137     Moves the cursor to the absolute position in the document specified by
1138     \a pos using a \c MoveMode specified by \a m. The cursor is positioned
1139     between characters.
1140
1141     \sa position(), movePosition(), anchor()
1142 */
1143 void QTextCursor::setPosition(int pos, MoveMode m)
1144 {
1145     if (!d || !d->priv)
1146         return;
1147
1148     if (pos < 0 || pos >= d->priv->length()) {
1149         qWarning("QTextCursor::setPosition: Position '%d' out of range", pos);
1150         return;
1151     }
1152
1153     d->setPosition(pos);
1154     if (m == MoveAnchor) {
1155         d->anchor = pos;
1156         d->adjusted_anchor = pos;
1157     } else { // keep anchor
1158         QTextCursor::MoveOperation op;
1159         if (pos < d->anchor)
1160             op = QTextCursor::Left;
1161         else
1162             op = QTextCursor::Right;
1163         d->adjustCursor(op);
1164     }
1165     d->setX();
1166 }
1167
1168 /*!
1169     Returns the absolute position of the cursor within the document.
1170     The cursor is positioned between characters.
1171
1172     \sa setPosition(), movePosition(), anchor(), positionInBlock()
1173 */
1174 int QTextCursor::position() const
1175 {
1176     if (!d || !d->priv)
1177         return -1;
1178     return d->position;
1179 }
1180
1181 /*!
1182     \since 4.7
1183     Returns the relative position of the cursor within the block.
1184     The cursor is positioned between characters.
1185
1186     This is equivalent to \c{ position() - block().position()}.
1187
1188     \sa position()
1189 */
1190 int QTextCursor::positionInBlock() const
1191 {
1192     if (!d || !d->priv)
1193         return 0;
1194     return d->position - d->block().position();
1195 }
1196
1197 /*!
1198     Returns the anchor position; this is the same as position() unless
1199     there is a selection in which case position() marks one end of the
1200     selection and anchor() marks the other end. Just like the cursor
1201     position, the anchor position is between characters.
1202
1203     \sa position(), setPosition(), movePosition(), selectionStart(), selectionEnd()
1204 */
1205 int QTextCursor::anchor() const
1206 {
1207     if (!d || !d->priv)
1208         return -1;
1209     return d->anchor;
1210 }
1211
1212 /*!
1213     \fn bool QTextCursor::movePosition(MoveOperation operation, MoveMode mode, int n)
1214
1215     Moves the cursor by performing the given \a operation \a n times, using the specified
1216     \a mode, and returns true if all operations were completed successfully; otherwise
1217     returns false.
1218
1219     For example, if this function is repeatedly used to seek to the end of the next
1220     word, it will eventually fail when the end of the document is reached.
1221
1222     By default, the move operation is performed once (\a n = 1).
1223
1224     If \a mode is \c KeepAnchor, the cursor selects the text it moves
1225     over. This is the same effect that the user achieves when they
1226     hold down the Shift key and move the cursor with the cursor keys.
1227
1228     \sa setVisualNavigation()
1229 */
1230 bool QTextCursor::movePosition(MoveOperation op, MoveMode mode, int n)
1231 {
1232     if (!d || !d->priv)
1233         return false;
1234     switch (op) {
1235     case Start:
1236     case StartOfLine:
1237     case End:
1238     case EndOfLine:
1239         n = 1;
1240         break;
1241     default: break;
1242     }
1243
1244     int previousPosition = d->position;
1245     for (; n > 0; --n) {
1246         if (!d->movePosition(op, mode))
1247             return false;
1248     }
1249
1250     if (d->visualNavigation && !d->block().isVisible()) {
1251         QTextBlock b = d->block();
1252         if (previousPosition < d->position) {
1253             while (!b.next().isVisible())
1254                 b = b.next();
1255             d->setPosition(b.position() + b.length() - 1);
1256         } else {
1257             while (!b.previous().isVisible())
1258                 b = b.previous();
1259             d->setPosition(b.position());
1260         }
1261         if (mode == QTextCursor::MoveAnchor)
1262             d->anchor = d->position;
1263         while (d->movePosition(op, mode)
1264                && !d->block().isVisible())
1265             ;
1266
1267     }
1268     return true;
1269 }
1270
1271 /*!
1272   \since 4.4
1273
1274   Returns true if the cursor does visual navigation; otherwise
1275   returns false.
1276
1277   Visual navigation means skipping over hidden text pragraphs. The
1278   default is false.
1279
1280   \sa setVisualNavigation(), movePosition()
1281  */
1282 bool QTextCursor::visualNavigation() const
1283 {
1284     return d ? d->visualNavigation : false;
1285 }
1286
1287 /*!
1288   \since 4.4
1289
1290   Sets visual navigation to \a b.
1291
1292   Visual navigation means skipping over hidden text pragraphs. The
1293   default is false.
1294
1295   \sa visualNavigation(), movePosition()
1296  */
1297 void QTextCursor::setVisualNavigation(bool b)
1298 {
1299     if (d)
1300         d->visualNavigation = b;
1301 }
1302
1303
1304 /*!
1305   \since 4.7
1306
1307   Sets the visual x position for vertical cursor movements to \a x.
1308
1309   The vertical movement x position is cleared automatically when the cursor moves horizontally, and kept
1310   unchanged when the cursor moves vertically. The mechanism allows the cursor to move up and down on a
1311   visually straight line with proportional fonts, and to gently "jump" over short lines.
1312
1313   A value of -1 indicates no predefined x position. It will then be set automatically the next time the
1314   cursor moves up or down.
1315
1316   \sa verticalMovementX()
1317   */
1318 void QTextCursor::setVerticalMovementX(int x)
1319 {
1320     if (d)
1321         d->x = x;
1322 }
1323
1324 /*! \since 4.7
1325
1326   Returns the visual x position for vertical cursor movements.
1327
1328   A value of -1 indicates no predefined x position. It will then be set automatically the next time the
1329   cursor moves up or down.
1330
1331   \sa setVerticalMovementX()
1332   */
1333 int QTextCursor::verticalMovementX() const
1334 {
1335     return d ? d->x : -1;
1336 }
1337
1338 /*!
1339   \since 4.7
1340
1341   Returns whether the cursor should keep its current position when text gets inserted at the position of the
1342   cursor.
1343
1344   The default is false;
1345
1346   \sa setKeepPositionOnInsert()
1347  */
1348 bool QTextCursor::keepPositionOnInsert() const
1349 {
1350     return d ? d->keepPositionOnInsert : false;
1351 }
1352
1353 /*!
1354   \since 4.7
1355
1356   Defines whether the cursor should keep its current position when text gets inserted at the current position of the
1357   cursor.
1358
1359   If \a b is true, the cursor keeps its current position when text gets inserted at the positing of the cursor.
1360   If \a b is false, the cursor moves along with the inserted text.
1361
1362   The default is false.
1363
1364   Note that a cursor always moves when text is inserted before the current position of the cursor, and it
1365   always keeps its position when text is inserted after the current position of the cursor.
1366
1367   \sa keepPositionOnInsert()
1368  */
1369 void QTextCursor::setKeepPositionOnInsert(bool b)
1370 {
1371     if (d)
1372         d->keepPositionOnInsert = b;
1373 }
1374
1375
1376
1377 /*!
1378     Inserts \a text at the current position, using the current
1379     character format.
1380
1381     If there is a selection, the selection is deleted and replaced by
1382     \a text, for example:
1383     \snippet code/src_gui_text_qtextcursor.cpp 0
1384     This clears any existing selection, selects the word at the cursor
1385     (i.e. from position() forward), and replaces the selection with
1386     the phrase "Hello World".
1387
1388     Any ASCII linefeed characters (\\n) in the inserted text are transformed
1389     into unicode block separators, corresponding to insertBlock() calls.
1390
1391     \sa charFormat(), hasSelection()
1392 */
1393 void QTextCursor::insertText(const QString &text)
1394 {
1395     QTextCharFormat fmt = charFormat();
1396     fmt.clearProperty(QTextFormat::ObjectType);
1397     insertText(text, fmt);
1398 }
1399
1400 /*!
1401     \fn void QTextCursor::insertText(const QString &text, const QTextCharFormat &format)
1402     \overload
1403
1404     Inserts \a text at the current position with the given \a format.
1405 */
1406 void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format)
1407 {
1408     if (!d || !d->priv)
1409         return;
1410
1411     Q_ASSERT(_format.isValid());
1412
1413     QTextCharFormat format = _format;
1414     format.clearProperty(QTextFormat::ObjectIndex);
1415
1416     bool hasEditBlock = false;
1417
1418     if (d->anchor != d->position) {
1419         hasEditBlock = true;
1420         d->priv->beginEditBlock();
1421         d->remove();
1422     }
1423
1424     if (!text.isEmpty()) {
1425         QTextFormatCollection *formats = d->priv->formatCollection();
1426         int formatIdx = formats->indexForFormat(format);
1427         Q_ASSERT(formats->format(formatIdx).isCharFormat());
1428
1429         QTextBlockFormat blockFmt = blockFormat();
1430
1431
1432         int textStart = d->priv->text.length();
1433         int blockStart = 0;
1434         d->priv->text += text;
1435         int textEnd = d->priv->text.length();
1436
1437         for (int i = 0; i < text.length(); ++i) {
1438             QChar ch = text.at(i);
1439
1440             const int blockEnd = i;
1441
1442             if (ch == QLatin1Char('\r')
1443                 && (i + 1) < text.length()
1444                 && text.at(i + 1) == QLatin1Char('\n')) {
1445                 ++i;
1446                 ch = text.at(i);
1447             }
1448
1449             if (ch == QLatin1Char('\n')
1450                 || ch == QChar::ParagraphSeparator
1451                 || ch == QTextBeginningOfFrame
1452                 || ch == QTextEndOfFrame
1453                 || ch == QLatin1Char('\r')) {
1454
1455                 if (!hasEditBlock) {
1456                     hasEditBlock = true;
1457                     d->priv->beginEditBlock();
1458                 }
1459
1460                 if (blockEnd > blockStart)
1461                     d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx);
1462
1463                 d->insertBlock(blockFmt, format);
1464                 blockStart = i + 1;
1465             }
1466         }
1467         if (textStart + blockStart < textEnd)
1468             d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx);
1469     }
1470     if (hasEditBlock)
1471         d->priv->endEditBlock();
1472     d->setX();
1473 }
1474
1475 /*!
1476     If there is no selected text, deletes the character \e at the
1477     current cursor position; otherwise deletes the selected text.
1478
1479     \sa deletePreviousChar(), hasSelection(), clearSelection()
1480 */
1481 void QTextCursor::deleteChar()
1482 {
1483     if (!d || !d->priv)
1484         return;
1485
1486     if (d->position != d->anchor) {
1487         removeSelectedText();
1488         return;
1489     }
1490
1491     if (!d->canDelete(d->position))
1492         return;
1493     d->adjusted_anchor = d->anchor =
1494                          d->priv->nextCursorPosition(d->anchor, QTextLayout::SkipCharacters);
1495     d->remove();
1496     d->setX();
1497 }
1498
1499 /*!
1500     If there is no selected text, deletes the character \e before the
1501     current cursor position; otherwise deletes the selected text.
1502
1503     \sa deleteChar(), hasSelection(), clearSelection()
1504 */
1505 void QTextCursor::deletePreviousChar()
1506 {
1507     if (!d || !d->priv)
1508         return;
1509
1510     if (d->position != d->anchor) {
1511         removeSelectedText();
1512         return;
1513     }
1514
1515     if (d->anchor < 1 || !d->canDelete(d->anchor-1))
1516         return;
1517     d->anchor--;
1518
1519     QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor);
1520     const QTextFragmentData * const frag = fragIt.value();
1521     int fpos = fragIt.position();
1522     QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
1523     if (d->anchor > fpos && uc.isLowSurrogate()) {
1524         // second half of a surrogate, check if we have the first half as well,
1525         // if yes delete both at once
1526         uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
1527         if (uc.isHighSurrogate())
1528             --d->anchor;
1529     }
1530
1531     d->adjusted_anchor = d->anchor;
1532     d->remove();
1533     d->setX();
1534 }
1535
1536 /*!
1537     Selects text in the document according to the given \a selection.
1538 */
1539 void QTextCursor::select(SelectionType selection)
1540 {
1541     if (!d || !d->priv)
1542         return;
1543
1544     clearSelection();
1545
1546     const QTextBlock block = d->block();
1547
1548     switch (selection) {
1549         case LineUnderCursor:
1550             movePosition(StartOfLine);
1551             movePosition(EndOfLine, KeepAnchor);
1552             break;
1553         case WordUnderCursor:
1554             movePosition(StartOfWord);
1555             movePosition(EndOfWord, KeepAnchor);
1556             break;
1557         case BlockUnderCursor:
1558             if (block.length() == 1) // no content
1559                 break;
1560             movePosition(StartOfBlock);
1561             // also select the paragraph separator
1562             if (movePosition(PreviousBlock)) {
1563                 movePosition(EndOfBlock);
1564                 movePosition(NextBlock, KeepAnchor);
1565             }
1566             movePosition(EndOfBlock, KeepAnchor);
1567             break;
1568         case Document:
1569             movePosition(Start);
1570             movePosition(End, KeepAnchor);
1571             break;
1572     }
1573 }
1574
1575 /*!
1576     Returns true if the cursor contains a selection; otherwise returns false.
1577 */
1578 bool QTextCursor::hasSelection() const
1579 {
1580     return !!d && d->position != d->anchor;
1581 }
1582
1583
1584 /*!
1585     Returns true if the cursor contains a selection that is not simply a
1586     range from selectionStart() to selectionEnd(); otherwise returns false.
1587
1588     Complex selections are ones that span at least two cells in a table;
1589     their extent is specified by selectedTableCells().
1590 */
1591 bool QTextCursor::hasComplexSelection() const
1592 {
1593     if (!d)
1594         return false;
1595
1596     return d->complexSelectionTable() != 0;
1597 }
1598
1599 /*!
1600     If the selection spans over table cells, \a firstRow is populated
1601     with the number of the first row in the selection, \a firstColumn
1602     with the number of the first column in the selection, and \a
1603     numRows and \a numColumns with the number of rows and columns in
1604     the selection. If the selection does not span any table cells the
1605     results are harmless but undefined.
1606 */
1607 void QTextCursor::selectedTableCells(int *firstRow, int *numRows, int *firstColumn, int *numColumns) const
1608 {
1609     *firstRow = -1;
1610     *firstColumn = -1;
1611     *numRows = -1;
1612     *numColumns = -1;
1613
1614     if (!d || d->position == d->anchor)
1615         return;
1616
1617     d->selectedTableCells(firstRow, numRows, firstColumn, numColumns);
1618 }
1619
1620
1621 /*!
1622     Clears the current selection by setting the anchor to the cursor position.
1623
1624     Note that it does \b{not} delete the text of the selection.
1625
1626     \sa removeSelectedText(), hasSelection()
1627 */
1628 void QTextCursor::clearSelection()
1629 {
1630     if (!d)
1631         return;
1632     d->adjusted_anchor = d->anchor = d->position;
1633     d->currentCharFormat = -1;
1634 }
1635
1636 /*!
1637     If there is a selection, its content is deleted; otherwise does
1638     nothing.
1639
1640     \sa hasSelection()
1641 */
1642 void QTextCursor::removeSelectedText()
1643 {
1644     if (!d || !d->priv || d->position == d->anchor)
1645         return;
1646
1647     d->priv->beginEditBlock();
1648     d->remove();
1649     d->priv->endEditBlock();
1650     d->setX();
1651 }
1652
1653 /*!
1654     Returns the start of the selection or position() if the
1655     cursor doesn't have a selection.
1656
1657     \sa selectionEnd(), position(), anchor()
1658 */
1659 int QTextCursor::selectionStart() const
1660 {
1661     if (!d || !d->priv)
1662         return -1;
1663     return qMin(d->position, d->adjusted_anchor);
1664 }
1665
1666 /*!
1667     Returns the end of the selection or position() if the cursor
1668     doesn't have a selection.
1669
1670     \sa selectionStart(), position(), anchor()
1671 */
1672 int QTextCursor::selectionEnd() const
1673 {
1674     if (!d || !d->priv)
1675         return -1;
1676     return qMax(d->position, d->adjusted_anchor);
1677 }
1678
1679 static void getText(QString &text, QTextDocumentPrivate *priv, const QString &docText, int pos, int end)
1680 {
1681     while (pos < end) {
1682         QTextDocumentPrivate::FragmentIterator fragIt = priv->find(pos);
1683         const QTextFragmentData * const frag = fragIt.value();
1684
1685         const int offsetInFragment = qMax(0, pos - fragIt.position());
1686         const int len = qMin(int(frag->size_array[0] - offsetInFragment), end - pos);
1687
1688         text += QString(docText.constData() + frag->stringPosition + offsetInFragment, len);
1689         pos += len;
1690     }
1691 }
1692
1693 /*!
1694     Returns the current selection's text (which may be empty). This
1695     only returns the text, with no rich text formatting information.
1696     If you want a document fragment (i.e. formatted rich text) use
1697     selection() instead.
1698
1699     \note If the selection obtained from an editor spans a line break,
1700     the text will contain a Unicode U+2029 paragraph separator character
1701     instead of a newline \c{\n} character. Use QString::replace() to
1702     replace these characters with newlines.
1703 */
1704 QString QTextCursor::selectedText() const
1705 {
1706     if (!d || !d->priv || d->position == d->anchor)
1707         return QString();
1708
1709     const QString docText = d->priv->buffer();
1710     QString text;
1711
1712     QTextTable *table = d->complexSelectionTable();
1713     if (table) {
1714         int row_start, col_start, num_rows, num_cols;
1715         selectedTableCells(&row_start, &num_rows, &col_start, &num_cols);
1716
1717         Q_ASSERT(row_start != -1);
1718         for (int r = row_start; r < row_start + num_rows; ++r) {
1719             for (int c = col_start; c < col_start + num_cols; ++c) {
1720                 QTextTableCell cell = table->cellAt(r, c);
1721                 int rspan = cell.rowSpan();
1722                 int cspan = cell.columnSpan();
1723                 if (rspan != 1) {
1724                     int cr = cell.row();
1725                     if (cr != r)
1726                         continue;
1727                 }
1728                 if (cspan != 1) {
1729                     int cc = cell.column();
1730                     if (cc != c)
1731                         continue;
1732                 }
1733
1734                 getText(text, d->priv, docText, cell.firstPosition(), cell.lastPosition());
1735             }
1736         }
1737     } else {
1738         getText(text, d->priv, docText, selectionStart(), selectionEnd());
1739     }
1740
1741     return text;
1742 }
1743
1744 /*!
1745     Returns the current selection (which may be empty) with all its
1746     formatting information. If you just want the selected text (i.e.
1747     plain text) use selectedText() instead.
1748
1749     \note Unlike QTextDocumentFragment::toPlainText(),
1750     selectedText() may include special unicode characters such as
1751     QChar::ParagraphSeparator.
1752
1753     \sa QTextDocumentFragment::toPlainText()
1754 */
1755 QTextDocumentFragment QTextCursor::selection() const
1756 {
1757     return QTextDocumentFragment(*this);
1758 }
1759
1760 /*!
1761     Returns the block that contains the cursor.
1762 */
1763 QTextBlock QTextCursor::block() const
1764 {
1765     if (!d || !d->priv)
1766         return QTextBlock();
1767     return d->block();
1768 }
1769
1770 /*!
1771     Returns the block format of the block the cursor is in.
1772
1773     \sa setBlockFormat(), charFormat()
1774  */
1775 QTextBlockFormat QTextCursor::blockFormat() const
1776 {
1777     if (!d || !d->priv)
1778         return QTextBlockFormat();
1779
1780     return d->block().blockFormat();
1781 }
1782
1783 /*!
1784     Sets the block format of the current block (or all blocks that
1785     are contained in the selection) to \a format.
1786
1787     \sa blockFormat(), mergeBlockFormat()
1788 */
1789 void QTextCursor::setBlockFormat(const QTextBlockFormat &format)
1790 {
1791     if (!d || !d->priv)
1792         return;
1793
1794     d->setBlockFormat(format, QTextDocumentPrivate::SetFormat);
1795 }
1796
1797 /*!
1798     Modifies the block format of the current block (or all blocks that
1799     are contained in the selection) with the block format specified by
1800     \a modifier.
1801
1802     \sa setBlockFormat(), blockFormat()
1803 */
1804 void QTextCursor::mergeBlockFormat(const QTextBlockFormat &modifier)
1805 {
1806     if (!d || !d->priv)
1807         return;
1808
1809     d->setBlockFormat(modifier, QTextDocumentPrivate::MergeFormat);
1810 }
1811
1812 /*!
1813     Returns the block character format of the block the cursor is in.
1814
1815     The block char format is the format used when inserting text at the
1816     beginning of an empty block.
1817
1818     \sa setBlockCharFormat()
1819  */
1820 QTextCharFormat QTextCursor::blockCharFormat() const
1821 {
1822     if (!d || !d->priv)
1823         return QTextCharFormat();
1824
1825     return d->block().charFormat();
1826 }
1827
1828 /*!
1829     Sets the block char format of the current block (or all blocks that
1830     are contained in the selection) to \a format.
1831
1832     \sa blockCharFormat()
1833 */
1834 void QTextCursor::setBlockCharFormat(const QTextCharFormat &format)
1835 {
1836     if (!d || !d->priv)
1837         return;
1838
1839     d->setBlockCharFormat(format, QTextDocumentPrivate::SetFormatAndPreserveObjectIndices);
1840 }
1841
1842 /*!
1843     Modifies the block char format of the current block (or all blocks that
1844     are contained in the selection) with the block format specified by
1845     \a modifier.
1846
1847     \sa setBlockCharFormat()
1848 */
1849 void QTextCursor::mergeBlockCharFormat(const QTextCharFormat &modifier)
1850 {
1851     if (!d || !d->priv)
1852         return;
1853
1854     d->setBlockCharFormat(modifier, QTextDocumentPrivate::MergeFormat);
1855 }
1856
1857 /*!
1858     Returns the format of the character immediately before the cursor
1859     position(). If the cursor is positioned at the beginning of a text
1860     block that is not empty then the format of the character
1861     immediately after the cursor is returned.
1862
1863     \sa insertText(), blockFormat()
1864  */
1865 QTextCharFormat QTextCursor::charFormat() const
1866 {
1867     if (!d || !d->priv)
1868         return QTextCharFormat();
1869
1870     int idx = d->currentCharFormat;
1871     if (idx == -1) {
1872         QTextBlock block = d->block();
1873
1874         int pos;
1875         if (d->position == block.position()
1876             && block.length() > 1)
1877             pos = d->position;
1878         else
1879             pos = d->position - 1;
1880
1881         if (pos == -1) {
1882             idx = d->priv->blockCharFormatIndex(d->priv->blockMap().firstNode());
1883         } else {
1884             Q_ASSERT(pos >= 0 && pos < d->priv->length());
1885
1886             QTextDocumentPrivate::FragmentIterator it = d->priv->find(pos);
1887             Q_ASSERT(!it.atEnd());
1888             idx = it.value()->format;
1889         }
1890     }
1891
1892     QTextCharFormat cfmt = d->priv->formatCollection()->charFormat(idx);
1893     cfmt.clearProperty(QTextFormat::ObjectIndex);
1894
1895     Q_ASSERT(cfmt.isValid());
1896     return cfmt;
1897 }
1898
1899 /*!
1900     Sets the cursor's current character format to the given \a
1901     format. If the cursor has a selection, the given \a format is
1902     applied to the current selection.
1903
1904     \sa hasSelection(), mergeCharFormat()
1905 */
1906 void QTextCursor::setCharFormat(const QTextCharFormat &format)
1907 {
1908     if (!d || !d->priv)
1909         return;
1910     if (d->position == d->anchor) {
1911         d->currentCharFormat = d->priv->formatCollection()->indexForFormat(format);
1912         return;
1913     }
1914     d->setCharFormat(format, QTextDocumentPrivate::SetFormatAndPreserveObjectIndices);
1915 }
1916
1917 /*!
1918     Merges the cursor's current character format with the properties
1919     described by format \a modifier. If the cursor has a selection,
1920     this function applies all the properties set in \a modifier to all
1921     the character formats that are part of the selection.
1922
1923     \sa hasSelection(), setCharFormat()
1924 */
1925 void QTextCursor::mergeCharFormat(const QTextCharFormat &modifier)
1926 {
1927     if (!d || !d->priv)
1928         return;
1929     if (d->position == d->anchor) {
1930         QTextCharFormat format = charFormat();
1931         format.merge(modifier);
1932         d->currentCharFormat = d->priv->formatCollection()->indexForFormat(format);
1933         return;
1934     }
1935
1936     d->setCharFormat(modifier, QTextDocumentPrivate::MergeFormat);
1937 }
1938
1939 /*!
1940     Returns true if the cursor is at the start of a block; otherwise
1941     returns false.
1942
1943     \sa atBlockEnd(), atStart()
1944 */
1945 bool QTextCursor::atBlockStart() const
1946 {
1947     if (!d || !d->priv)
1948         return false;
1949
1950     return d->position == d->block().position();
1951 }
1952
1953 /*!
1954     Returns true if the cursor is at the end of a block; otherwise
1955     returns false.
1956
1957     \sa atBlockStart(), atEnd()
1958 */
1959 bool QTextCursor::atBlockEnd() const
1960 {
1961     if (!d || !d->priv)
1962         return false;
1963
1964     return d->position == d->block().position() + d->block().length() - 1;
1965 }
1966
1967 /*!
1968     Returns true if the cursor is at the start of the document;
1969     otherwise returns false.
1970
1971     \sa atBlockStart(), atEnd()
1972 */
1973 bool QTextCursor::atStart() const
1974 {
1975     if (!d || !d->priv)
1976         return false;
1977
1978     return d->position == 0;
1979 }
1980
1981 /*!
1982     \since 4.6
1983
1984     Returns true if the cursor is at the end of the document;
1985     otherwise returns false.
1986
1987     \sa atStart(), atBlockEnd()
1988 */
1989 bool QTextCursor::atEnd() const
1990 {
1991     if (!d || !d->priv)
1992         return false;
1993
1994     return d->position == d->priv->length() - 1;
1995 }
1996
1997 /*!
1998     Inserts a new empty block at the cursor position() with the
1999     current blockFormat() and charFormat().
2000
2001     \sa setBlockFormat()
2002 */
2003 void QTextCursor::insertBlock()
2004 {
2005     insertBlock(blockFormat());
2006 }
2007
2008 /*!
2009     \overload
2010
2011     Inserts a new empty block at the cursor position() with block
2012     format \a format and the current charFormat() as block char format.
2013
2014     \sa setBlockFormat()
2015 */
2016 void QTextCursor::insertBlock(const QTextBlockFormat &format)
2017 {
2018     QTextCharFormat charFmt = charFormat();
2019     charFmt.clearProperty(QTextFormat::ObjectType);
2020     insertBlock(format, charFmt);
2021 }
2022
2023 /*!
2024     \fn void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
2025     \overload
2026
2027     Inserts a new empty block at the cursor position() with block
2028     format \a format and \a charFormat as block char format.
2029
2030     \sa setBlockFormat()
2031 */
2032 void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &_charFormat)
2033 {
2034     if (!d || !d->priv)
2035         return;
2036
2037     QTextCharFormat charFormat = _charFormat;
2038     charFormat.clearProperty(QTextFormat::ObjectIndex);
2039
2040     d->priv->beginEditBlock();
2041     d->remove();
2042     d->insertBlock(format, charFormat);
2043     d->priv->endEditBlock();
2044     d->setX();
2045 }
2046
2047 /*!
2048     Inserts a new block at the current position and makes it the first
2049     list item of a newly created list with the given \a format. Returns
2050     the created list.
2051
2052     \sa currentList(), createList(), insertBlock()
2053  */
2054 QTextList *QTextCursor::insertList(const QTextListFormat &format)
2055 {
2056     insertBlock();
2057     return createList(format);
2058 }
2059
2060 /*!
2061     \overload
2062
2063     Inserts a new block at the current position and makes it the first
2064     list item of a newly created list with the given \a style. Returns
2065     the created list.
2066
2067     \sa currentList(), createList(), insertBlock()
2068  */
2069 QTextList *QTextCursor::insertList(QTextListFormat::Style style)
2070 {
2071     insertBlock();
2072     return createList(style);
2073 }
2074
2075 /*!
2076     Creates and returns a new list with the given \a format, and makes the
2077     current paragraph the cursor is in the first list item.
2078
2079     \sa insertList(), currentList()
2080  */
2081 QTextList *QTextCursor::createList(const QTextListFormat &format)
2082 {
2083     if (!d || !d->priv)
2084         return 0;
2085
2086     QTextList *list = static_cast<QTextList *>(d->priv->createObject(format));
2087     QTextBlockFormat modifier;
2088     modifier.setObjectIndex(list->objectIndex());
2089     mergeBlockFormat(modifier);
2090     return list;
2091 }
2092
2093 /*!
2094     \overload
2095
2096     Creates and returns a new list with the given \a style, making the
2097     cursor's current paragraph the first list item.
2098
2099     The style to be used is defined by the QTextListFormat::Style enum.
2100
2101     \sa insertList(), currentList()
2102  */
2103 QTextList *QTextCursor::createList(QTextListFormat::Style style)
2104 {
2105     QTextListFormat fmt;
2106     fmt.setStyle(style);
2107     return createList(fmt);
2108 }
2109
2110 /*!
2111     Returns the current list if the cursor position() is inside a
2112     block that is part of a list; otherwise returns 0.
2113
2114     \sa insertList(), createList()
2115  */
2116 QTextList *QTextCursor::currentList() const
2117 {
2118     if (!d || !d->priv)
2119         return 0;
2120
2121     QTextBlockFormat b = blockFormat();
2122     QTextObject *o = d->priv->objectForFormat(b);
2123     return qobject_cast<QTextList *>(o);
2124 }
2125
2126 /*!
2127     \fn QTextTable *QTextCursor::insertTable(int rows, int columns)
2128
2129     \overload
2130
2131     Creates a new table with the given number of \a rows and \a columns,
2132     inserts it at the current cursor position() in the document, and returns
2133     the table object. The cursor is moved to the beginning of the first cell.
2134
2135     There must be at least one row and one column in the table.
2136
2137     \sa currentTable()
2138  */
2139 QTextTable *QTextCursor::insertTable(int rows, int cols)
2140 {
2141     return insertTable(rows, cols, QTextTableFormat());
2142 }
2143
2144 /*!
2145     \fn QTextTable *QTextCursor::insertTable(int rows, int columns, const QTextTableFormat &format)
2146
2147     Creates a new table with the given number of \a rows and \a columns
2148     in the specified \a format, inserts it at the current cursor position()
2149     in the document, and returns the table object. The cursor is moved to
2150     the beginning of the first cell.
2151
2152     There must be at least one row and one column in the table.
2153
2154     \sa currentTable()
2155 */
2156 QTextTable *QTextCursor::insertTable(int rows, int cols, const QTextTableFormat &format)
2157 {
2158     if(!d || !d->priv || rows == 0 || cols == 0)
2159         return 0;
2160
2161     int pos = d->position;
2162     QTextTable *t = QTextTablePrivate::createTable(d->priv, d->position, rows, cols, format);
2163     d->setPosition(pos+1);
2164     // ##### what should we do if we have a selection?
2165     d->anchor = d->position;
2166     d->adjusted_anchor = d->anchor;
2167     return t;
2168 }
2169
2170 /*!
2171     Returns a pointer to the current table if the cursor position()
2172     is inside a block that is part of a table; otherwise returns 0.
2173
2174     \sa insertTable()
2175 */
2176 QTextTable *QTextCursor::currentTable() const
2177 {
2178     if(!d || !d->priv)
2179         return 0;
2180
2181     QTextFrame *frame = d->priv->frameAt(d->position);
2182     while (frame) {
2183         QTextTable *table = qobject_cast<QTextTable *>(frame);
2184         if (table)
2185             return table;
2186         frame = frame->parentFrame();
2187     }
2188     return 0;
2189 }
2190
2191 /*!
2192     Inserts a frame with the given \a format at the current cursor position(),
2193     moves the cursor position() inside the frame, and returns the frame.
2194
2195     If the cursor holds a selection, the whole selection is moved inside the
2196     frame.
2197
2198     \sa hasSelection()
2199 */
2200 QTextFrame *QTextCursor::insertFrame(const QTextFrameFormat &format)
2201 {
2202     if (!d || !d->priv)
2203         return 0;
2204
2205     return d->priv->insertFrame(selectionStart(), selectionEnd(), format);
2206 }
2207
2208 /*!
2209     Returns a pointer to the current frame. Returns 0 if the cursor is invalid.
2210
2211     \sa insertFrame()
2212 */
2213 QTextFrame *QTextCursor::currentFrame() const
2214 {
2215     if(!d || !d->priv)
2216         return 0;
2217
2218     return d->priv->frameAt(d->position);
2219 }
2220
2221
2222 /*!
2223     Inserts the text \a fragment at the current position().
2224 */
2225 void QTextCursor::insertFragment(const QTextDocumentFragment &fragment)
2226 {
2227     if (!d || !d->priv || fragment.isEmpty())
2228         return;
2229
2230     d->priv->beginEditBlock();
2231     d->remove();
2232     fragment.d->insert(*this);
2233     d->priv->endEditBlock();
2234
2235     if (fragment.d && fragment.d->doc)
2236         d->priv->mergeCachedResources(fragment.d->doc->docHandle());
2237 }
2238
2239 /*!
2240     \since 4.2
2241     Inserts the text \a html at the current position(). The text is interpreted as
2242     HTML.
2243
2244     \note When using this function with a style sheet, the style sheet will
2245     only apply to the current block in the document. In order to apply a style
2246     sheet throughout a document, use QTextDocument::setDefaultStyleSheet()
2247     instead.
2248 */
2249
2250 #ifndef QT_NO_TEXTHTMLPARSER
2251
2252 void QTextCursor::insertHtml(const QString &html)
2253 {
2254     if (!d || !d->priv)
2255         return;
2256     QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(html, d->priv->document());
2257     insertFragment(fragment);
2258 }
2259
2260 #endif // QT_NO_TEXTHTMLPARSER
2261
2262 /*!
2263     \overload
2264     \since 4.2
2265
2266     Inserts the image defined by the given \a format at the cursor's current position
2267     with the specified \a alignment.
2268
2269     \sa position()
2270 */
2271 void QTextCursor::insertImage(const QTextImageFormat &format, QTextFrameFormat::Position alignment)
2272 {
2273     if (!d || !d->priv)
2274         return;
2275
2276     QTextFrameFormat ffmt;
2277     ffmt.setPosition(alignment);
2278     QTextObject *obj = d->priv->createObject(ffmt);
2279
2280     QTextImageFormat fmt = format;
2281     fmt.setObjectIndex(obj->objectIndex());
2282
2283     d->priv->beginEditBlock();
2284     d->remove();
2285     const int idx = d->priv->formatCollection()->indexForFormat(fmt);
2286     d->priv->insert(d->position, QString(QChar(QChar::ObjectReplacementCharacter)), idx);
2287     d->priv->endEditBlock();
2288 }
2289
2290 /*!
2291     Inserts the image defined by \a format at the current position().
2292 */
2293 void QTextCursor::insertImage(const QTextImageFormat &format)
2294 {
2295     insertText(QString(QChar::ObjectReplacementCharacter), format);
2296 }
2297
2298 /*!
2299     \overload
2300
2301     Convenience method for inserting the image with the given \a name at the
2302     current position().
2303
2304     \snippet code/src_gui_text_qtextcursor.cpp 1
2305 */
2306 void QTextCursor::insertImage(const QString &name)
2307 {
2308     QTextImageFormat format;
2309     format.setName(name);
2310     insertImage(format);
2311 }
2312
2313 /*!
2314     \since 4.5
2315     \overload
2316
2317     Convenience function for inserting the given \a image with an optional
2318     \a name at the current position().
2319 */
2320 void QTextCursor::insertImage(const QImage &image, const QString &name)
2321 {
2322     if (image.isNull()) {
2323         qWarning("QTextCursor::insertImage: attempt to add an invalid image");
2324         return;
2325     }
2326     QString imageName = name;
2327     if (name.isEmpty())
2328         imageName = QString::number(image.cacheKey());
2329     d->priv->document()->addResource(QTextDocument::ImageResource, QUrl(imageName), image);
2330     QTextImageFormat format;
2331     format.setName(imageName);
2332     insertImage(format);
2333 }
2334
2335 /*!
2336     \fn bool QTextCursor::operator!=(const QTextCursor &other) const
2337
2338     Returns true if the \a other cursor is at a different position in
2339     the document as this cursor; otherwise returns false.
2340 */
2341 bool QTextCursor::operator!=(const QTextCursor &rhs) const
2342 {
2343     return !operator==(rhs);
2344 }
2345
2346 /*!
2347     \fn bool QTextCursor::operator<(const QTextCursor &other) const
2348
2349     Returns true if the \a other cursor is positioned later in the
2350     document than this cursor; otherwise returns false.
2351 */
2352 bool QTextCursor::operator<(const QTextCursor &rhs) const
2353 {
2354     if (!d)
2355         return !!rhs.d;
2356
2357     if (!rhs.d)
2358         return false;
2359
2360     Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<", "cannot compare cursors attached to different documents");
2361
2362     return d->position < rhs.d->position;
2363 }
2364
2365 /*!
2366     \fn bool QTextCursor::operator<=(const QTextCursor &other) const
2367
2368     Returns true if the \a other cursor is positioned later or at the
2369     same position in the document as this cursor; otherwise returns
2370     false.
2371 */
2372 bool QTextCursor::operator<=(const QTextCursor &rhs) const
2373 {
2374     if (!d)
2375         return true;
2376
2377     if (!rhs.d)
2378         return false;
2379
2380     Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator<=", "cannot compare cursors attached to different documents");
2381
2382     return d->position <= rhs.d->position;
2383 }
2384
2385 /*!
2386     \fn bool QTextCursor::operator==(const QTextCursor &other) const
2387
2388     Returns true if the \a other cursor is at the same position in the
2389     document as this cursor; otherwise returns false.
2390 */
2391 bool QTextCursor::operator==(const QTextCursor &rhs) const
2392 {
2393     if (!d)
2394         return !rhs.d;
2395
2396     if (!rhs.d)
2397         return false;
2398
2399     return d->position == rhs.d->position && d->priv == rhs.d->priv;
2400 }
2401
2402 /*!
2403     \fn bool QTextCursor::operator>=(const QTextCursor &other) const
2404
2405     Returns true if the \a other cursor is positioned earlier or at the
2406     same position in the document as this cursor; otherwise returns
2407     false.
2408 */
2409 bool QTextCursor::operator>=(const QTextCursor &rhs) const
2410 {
2411     if (!d)
2412         return false;
2413
2414     if (!rhs.d)
2415         return true;
2416
2417     Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>=", "cannot compare cursors attached to different documents");
2418
2419     return d->position >= rhs.d->position;
2420 }
2421
2422 /*!
2423     \fn bool QTextCursor::operator>(const QTextCursor &other) const
2424
2425     Returns true if the \a other cursor is positioned earlier in the
2426     document than this cursor; otherwise returns false.
2427 */
2428 bool QTextCursor::operator>(const QTextCursor &rhs) const
2429 {
2430     if (!d)
2431         return false;
2432
2433     if (!rhs.d)
2434         return true;
2435
2436     Q_ASSERT_X(d->priv == rhs.d->priv, "QTextCursor::operator>", "cannot compare cursors attached to different documents");
2437
2438     return d->position > rhs.d->position;
2439 }
2440
2441 /*!
2442     Indicates the start of a block of editing operations on the
2443     document that should appear as a single operation from an
2444     undo/redo point of view.
2445
2446     For example:
2447
2448     \snippet code/src_gui_text_qtextcursor.cpp 2
2449
2450     The call to undo() will cause both insertions to be undone,
2451     causing both "World" and "Hello" to be removed.
2452
2453     It is possible to nest calls to beginEditBlock and endEditBlock. The
2454     top-most pair will determine the scope of the undo/redo operation.
2455
2456     \sa endEditBlock()
2457  */
2458 void QTextCursor::beginEditBlock()
2459 {
2460     if (!d || !d->priv)
2461         return;
2462
2463     if (d->priv->editBlock == 0) // we are the initial edit block, store current cursor position for undo
2464         d->priv->editBlockCursorPosition = d->position;
2465
2466     d->priv->beginEditBlock();
2467 }
2468
2469 /*!
2470     Like beginEditBlock() indicates the start of a block of editing operations
2471     that should appear as a single operation for undo/redo. However unlike
2472     beginEditBlock() it does not start a new block but reverses the previous call to
2473     endEditBlock() and therefore makes following operations part of the previous edit block created.
2474
2475     For example:
2476
2477     \snippet code/src_gui_text_qtextcursor.cpp 3
2478
2479     The call to undo() will cause all three insertions to be undone.
2480
2481     \sa beginEditBlock(), endEditBlock()
2482  */
2483 void QTextCursor::joinPreviousEditBlock()
2484 {
2485     if (!d || !d->priv)
2486         return;
2487
2488     d->priv->joinPreviousEditBlock();
2489 }
2490
2491 /*!
2492     Indicates the end of a block of editing operations on the document
2493     that should appear as a single operation from an undo/redo point
2494     of view.
2495
2496     \sa beginEditBlock()
2497  */
2498
2499 void QTextCursor::endEditBlock()
2500 {
2501     if (!d || !d->priv)
2502         return;
2503
2504     d->priv->endEditBlock();
2505 }
2506
2507 /*!
2508     Returns true if this cursor and \a other are copies of each other, i.e.
2509     one of them was created as a copy of the other and neither has moved since.
2510     This is much stricter than equality.
2511
2512     \sa operator=(), operator==()
2513 */
2514 bool QTextCursor::isCopyOf(const QTextCursor &other) const
2515 {
2516     return d == other.d;
2517 }
2518
2519 /*!
2520     \since 4.2
2521     Returns the number of the block the cursor is in, or 0 if the cursor is invalid.
2522
2523     Note that this function only makes sense in documents without complex objects such
2524     as tables or frames.
2525 */
2526 int QTextCursor::blockNumber() const
2527 {
2528     if (!d || !d->priv)
2529         return 0;
2530
2531     return d->block().blockNumber();
2532 }
2533
2534
2535 /*!
2536     \since 4.2
2537     Returns the position of the cursor within its containing line.
2538
2539     Note that this is the column number relative to a wrapped line,
2540     not relative to the block (i.e. the paragraph).
2541
2542     You probably want to call positionInBlock() instead.
2543
2544     \sa positionInBlock()
2545 */
2546 int QTextCursor::columnNumber() const
2547 {
2548     if (!d || !d->priv)
2549         return 0;
2550
2551     QTextBlock block = d->block();
2552     if (!block.isValid())
2553         return 0;
2554
2555     const QTextLayout *layout = d->blockLayout(block);
2556
2557     const int relativePos = d->position - block.position();
2558
2559     if (layout->lineCount() == 0)
2560         return relativePos;
2561
2562     QTextLine line = layout->lineForTextPosition(relativePos);
2563     if (!line.isValid())
2564         return 0;
2565     return relativePos - line.textStart();
2566 }
2567
2568 /*!
2569     \since 4.5
2570     Returns the document this cursor is associated with.
2571 */
2572 QTextDocument *QTextCursor::document() const
2573 {
2574     if (d->priv)
2575         return d->priv->document();
2576     return 0; // document went away
2577 }
2578
2579 /*!
2580     \enum Qt::CursorMoveStyle
2581
2582     This enum describes the movement style available to text cursors. The options
2583     are:
2584
2585     \value LogicalMoveStyle Within a left-to-right text block, decrease cursor
2586     position when pressing left arrow key, increase cursor position when pressing
2587     the right arrow key. If the text block is right-to-left, the opposite behavior
2588     applies.
2589     \value VisualMoveStyle Pressing the left arrow key will always cause the cursor
2590     to move left, regardless of the text's writing direction. Pressing the right
2591     arrow key will always cause the cursor to move right.
2592 */
2593
2594 QT_END_NAMESPACE