Fix cursor position adjustment when removing strings
[qt:qt.git] / tests / auto / qtextcursor / tst_qtextcursor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45
46 #include <qtextdocument.h>
47 #include <qtexttable.h>
48 #include <qvariant.h>
49 #include <qtextdocumentfragment.h>
50 #include <qabstracttextdocumentlayout.h>
51 #include <qtextlayout.h>
52 #include <qtextcursor.h>
53 #include <qdebug.h>
54
55 //TESTED_FILES=gui/text/qtextcursor.cpp gui/text/qtextcursor_p.h
56
57 QT_FORWARD_DECLARE_CLASS(QTextDocument)
58
59 class tst_QTextCursor : public QObject
60 {
61     Q_OBJECT
62
63 public:
64     tst_QTextCursor();
65
66
67 public slots:
68     void init();
69     void cleanup();
70 private slots:
71     void navigation1();
72     void navigation2_data();
73     void navigation2();
74     void navigation3();
75     void navigation4();
76     void navigation5();
77     void navigation6();
78     void navigation7();
79     void navigation8();
80     void navigation9();
81     void navigation10();
82     void movePositionEndOfLine();
83     void insertBlock();
84     void insertWithBlockSeparator1();
85     void insertWithBlockSeparator2();
86     void insertWithBlockSeparator3();
87     void insertWithBlockSeparator4();
88     void clearObjectType1();
89     void clearObjectType2();
90     void clearObjectType3();
91     void comparisonOperators1();
92     void comparisonOperators2();
93     void selection1();
94     void dontCopyTableAttributes();
95
96     void checkFrame1();
97     void checkFrame2();
98
99     void tableMovement();
100     void selectionsInTable();
101
102     void insertBlockToUseCharFormat();
103
104     void selectedText();
105
106     void insertBlockShouldRemoveSelection();
107     void insertBlockShouldRemoveSelection2();
108     void mergeCellShouldUpdateSelection();
109
110     void joinPreviousEditBlock();
111
112     void setBlockFormatInTable();
113
114     void blockCharFormat();
115     void blockCharFormat2();
116     void blockCharFormat3();
117     void blockCharFormatOnSelection();
118
119     void anchorInitialized1();
120     void anchorInitialized2();
121     void anchorInitialized3();
122
123     void selectWord();
124     void selectWordWithSeparators_data();
125     void selectWordWithSeparators();
126     void startOfWord();
127     void selectBlock();
128     void selectVisually();
129
130     void insertText();
131
132     void insertFragmentShouldUseCurrentCharFormat();
133
134     void endOfLine();
135
136     void editBlocksDuringRemove();
137     void selectAllDuringRemove();
138
139     void update_data();
140     void update();
141
142     void disallowSettingObjectIndicesOnCharFormats();
143
144     void blockAndColumnNumber();
145
146     void clearCells();
147
148     void task244408_wordUnderCursor_data();
149     void task244408_wordUnderCursor();
150
151     void adjustCursorsOnInsert();
152
153     void cursorPositionWithBlockUndoAndRedo();
154     void cursorPositionWithBlockUndoAndRedo2();
155     void cursorPositionWithBlockUndoAndRedo3();
156
157 private:
158     int blockCount();
159
160     QTextDocument *doc;
161     QTextCursor cursor;
162 };
163
164 Q_DECLARE_METATYPE(QList<QVariant>)
165
166 tst_QTextCursor::tst_QTextCursor()
167 {}
168
169 void tst_QTextCursor::init()
170 {
171     doc = new QTextDocument;
172     cursor = QTextCursor(doc);
173 }
174
175 void tst_QTextCursor::cleanup()
176 {
177     cursor = QTextCursor();
178     delete doc;
179     doc = 0;
180 }
181
182 void tst_QTextCursor::navigation1()
183 {
184
185     cursor.insertText("Hello World");
186     QVERIFY(doc->toPlainText() == "Hello World");
187
188     cursor.movePosition(QTextCursor::End);
189     QVERIFY(cursor.position() == 11);
190     cursor.deletePreviousChar();
191     QVERIFY(cursor.position() == 10);
192     cursor.deletePreviousChar();
193     cursor.deletePreviousChar();
194     cursor.deletePreviousChar();
195     cursor.deletePreviousChar();
196     cursor.deletePreviousChar();
197     QVERIFY(doc->toPlainText() == "Hello");
198
199     QTextCursor otherCursor(doc);
200     otherCursor.movePosition(QTextCursor::Start);
201     otherCursor.movePosition(QTextCursor::Right);
202     cursor = otherCursor;
203     cursor.movePosition(QTextCursor::Right);
204     QVERIFY(cursor != otherCursor);
205     otherCursor.insertText("Hey");
206     QVERIFY(cursor.position() == 5);
207
208     doc->undo();
209     QVERIFY(cursor.position() == 2);
210     doc->redo();
211     QVERIFY(cursor.position() == 5);
212
213     doc->undo();
214
215     doc->undo();
216     QVERIFY(doc->toPlainText() == "Hello World");
217
218     cursor.movePosition(QTextCursor::Start);
219     cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 6);
220     QVERIFY(cursor.position() == 6);
221     otherCursor = cursor;
222     otherCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, 2);
223     otherCursor.deletePreviousChar();
224     otherCursor.deletePreviousChar();
225     otherCursor.deletePreviousChar();
226     QVERIFY(cursor.position() == 5);
227
228     cursor.movePosition(QTextCursor::End);
229     cursor.insertBlock();
230     {
231         int oldPos = cursor.position();
232         cursor.movePosition(QTextCursor::End);
233         QVERIFY(cursor.position() == oldPos);
234     }
235     QVERIFY(cursor.atBlockStart());
236     QVERIFY(cursor.position() == 9);
237
238     QTextCharFormat fmt;
239     fmt.setForeground(Qt::blue);
240     cursor.insertText("Test", fmt);
241     QVERIFY(fmt == cursor.charFormat());
242     QVERIFY(cursor.position() == 13);
243 }
244
245 void tst_QTextCursor::navigation2_data()
246 {
247     QTest::addColumn<QStringList>("sl");
248     QTest::addColumn<QList<QVariant> >("movement");
249     QTest::addColumn<int>("finalPos");
250
251     QTest::newRow("startBlock1") << QStringList("Happy happy happy joy joy joy")
252                               << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)) << 0;
253     QTest::newRow("endBlock1") << QStringList("Happy happy happy joy joy joy")
254                             << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
255                                      << QVariant(QTextCursor::EndOfBlock)) << 29;
256     QTest::newRow("startBlock2") << QStringList("Happy happy happy joy joy joy")
257                               << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
258                                      << QVariant(QTextCursor::EndOfBlock)
259                                      << QVariant(QTextCursor::StartOfBlock)) << 0;
260     QTest::newRow("endBlock2") << QStringList("Happy happy happy joy joy joy")
261                             << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
262                                      << QVariant(QTextCursor::EndOfBlock)
263                                      << QVariant(QTextCursor::StartOfBlock)
264                                      << QVariant(QTextCursor::EndOfBlock)
265                                      ) << 29;
266     QTest::newRow("multiBlock1") << (QStringList() << QString("Happy happy happy")
267                                                 << QString("Joy Joy Joy"))
268                              << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock))
269                              << 18;
270     QTest::newRow("multiBlock2") << (QStringList() << QString("Happy happy happy")
271                                                 << QString("Joy Joy Joy"))
272                              << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
273                                                    << QVariant(QTextCursor::EndOfBlock))
274                              << 29;
275     QTest::newRow("multiBlock3") << (QStringList() << QString("Happy happy happy")
276                                                 << QString("Joy Joy Joy"))
277                              << (QList<QVariant>() << QVariant(QTextCursor::StartOfBlock)
278                                                    << QVariant(QTextCursor::StartOfBlock))
279                              << 18;
280     QTest::newRow("multiBlock4") << (QStringList() << QString("Happy happy happy")
281                                                 << QString("Joy Joy Joy"))
282                              << (QList<QVariant>() << QVariant(QTextCursor::Start)
283                                                    << QVariant(QTextCursor::EndOfBlock))
284                              << 17;
285     QTest::newRow("multiBlock5") << (QStringList() << QString("Happy happy happy")
286                                                 << QString("Joy Joy Joy"))
287                              << (QList<QVariant>() << QVariant(QTextCursor::Start)
288                                                    << QVariant(QTextCursor::EndOfBlock)
289                                                    << QVariant(QTextCursor::EndOfBlock))
290                              << 17;
291     QTest::newRow("multiBlock6") << (QStringList() << QString("Happy happy happy")
292                                                 << QString("Joy Joy Joy"))
293                              << (QList<QVariant>() << QVariant(QTextCursor::End)
294                                                    << QVariant(QTextCursor::StartOfBlock))
295                              << 18;
296     QTest::newRow("multiBlock7") << (QStringList() << QString("Happy happy happy")
297                                                 << QString("Joy Joy Joy"))
298                              << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock))
299                              << 0;
300     QTest::newRow("multiBlock8") << (QStringList() << QString("Happy happy happy")
301                                                 << QString("Joy Joy Joy"))
302                              << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
303                                                    << QVariant(QTextCursor::EndOfBlock))
304                              << 17;
305     QTest::newRow("multiBlock9") << (QStringList() << QString("Happy happy happy")
306                                                 << QString("Joy Joy Joy"))
307                              << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
308                                                    << QVariant(QTextCursor::NextBlock))
309                              << 18;
310     QTest::newRow("multiBlock10") << (QStringList() << QString("Happy happy happy")
311                                                 << QString("Joy Joy Joy"))
312                                << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
313                                                      << QVariant(QTextCursor::NextBlock)
314                                                      << QVariant(QTextCursor::NextBlock))
315                                << 18;
316     QTest::newRow("multiBlock11") << (QStringList() << QString("Happy happy happy")
317                                                 << QString("Joy Joy Joy"))
318                                << (QList<QVariant>() << QVariant(QTextCursor::PreviousBlock)
319                                                      << QVariant(QTextCursor::NextBlock)
320                                                      << QVariant(QTextCursor::EndOfBlock))
321                                << 29;
322     QTest::newRow("PreviousWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
323                                 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord))
324                                 << 26;
325     QTest::newRow("PreviousWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
326                                 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
327                                                       << QVariant(QTextCursor::PreviousWord))
328                                 << 22;
329     QTest::newRow("EndWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
330                                 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
331                                                       << QVariant(QTextCursor::PreviousWord)
332                                                       << QVariant(QTextCursor::EndOfWord))
333                                 << 25;
334     QTest::newRow("NextWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
335                                 << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
336                                                       << QVariant(QTextCursor::PreviousWord)
337                                                       << QVariant(QTextCursor::NextWord))
338                                 << 26;
339     QTest::newRow("NextWord2") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
340                                 << (QList<QVariant>() << QVariant(QTextCursor::Start)
341                                                       << QVariant(QTextCursor::NextWord)
342                                                       << QVariant(QTextCursor::EndOfWord))
343                                 << 11;
344     QTest::newRow("StartWord1") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
345                              << (QList<QVariant>() << QVariant(QTextCursor::PreviousWord)
346                                                    << QVariant(QTextCursor::PreviousWord)
347                                                    << QVariant(QTextCursor::StartOfWord))
348                              << 22;
349     QTest::newRow("StartWord3") << (QStringList() << QString("Happy happy happy Joy Joy Joy"))
350                              << (QList<QVariant>() << QVariant(QTextCursor::Start)
351                                                    << QVariant(QTextCursor::NextWord)
352                                                    << QVariant(QTextCursor::EndOfWord)
353                                                    << QVariant(QTextCursor::StartOfWord))
354                              << 6;
355
356     QTest::newRow("PreviousCharacter") << (QStringList() << QString("Happy happy Joy Joy"))
357                              << (QList<QVariant>() << QVariant(QTextCursor::PreviousCharacter)
358                                                    << QVariant(QTextCursor::PreviousCharacter))
359                              << 17;
360 }
361
362 void tst_QTextCursor::navigation2()
363 {
364     QFETCH(QStringList, sl);
365     QFETCH(QList<QVariant>, movement);
366     int i;
367     for (i = 0; i < sl.size(); ++i) {
368         cursor.insertText(sl.at(i));
369         if (i < sl.size() - 1)
370             cursor.insertBlock();
371     }
372
373     for (i = 0; i < movement.size(); ++i)
374         cursor.movePosition(QTextCursor::MoveOperation(movement.at(i).toInt()));
375     QTEST(cursor.position(), "finalPos");
376 }
377
378 void tst_QTextCursor::navigation3()
379 {
380     cursor.insertText("a");
381     cursor.deletePreviousChar();
382     QCOMPARE(cursor.position(), 0);
383     QVERIFY(doc->toPlainText().isEmpty());
384 }
385
386 void tst_QTextCursor::navigation4()
387 {
388     cursor.insertText("  Test  ");
389
390     cursor.setPosition(4);
391     cursor.movePosition(QTextCursor::EndOfWord);
392     QCOMPARE(cursor.position(), 6);
393 }
394
395 void tst_QTextCursor::navigation5()
396 {
397     cursor.insertText("Test");
398     cursor.insertBlock();
399     cursor.insertText("Test");
400
401     cursor.setPosition(0);
402     cursor.movePosition(QTextCursor::EndOfBlock);
403     QCOMPARE(cursor.position(), 4);
404 }
405
406 void tst_QTextCursor::navigation6()
407 {
408     // triger creation of document layout, so that QTextLines are there
409     doc->documentLayout();
410     doc->setTextWidth(1000);
411
412     cursor.insertText("Test    ");
413
414     cursor.movePosition(QTextCursor::Start);
415     cursor.movePosition(QTextCursor::EndOfLine);
416     QCOMPARE(cursor.position(), 8);
417 }
418
419 void tst_QTextCursor::navigation7()
420 {
421     QVERIFY(doc->isEmpty());
422     for (int i = QTextCursor::Start; i <= QTextCursor::WordRight; ++i)
423         QVERIFY(!cursor.movePosition(QTextCursor::MoveOperation(i)));
424
425     doc->setPlainText("Hello World");
426     cursor.movePosition(QTextCursor::Start);
427     do {
428     } while (cursor.movePosition(QTextCursor::NextCharacter));
429     QVERIFY(true /*reached*/);
430 }
431
432 void tst_QTextCursor::navigation8()
433 {
434     cursor.insertList(QTextListFormat::ListDecimal);
435     QCOMPARE(cursor.position(), 1);
436     cursor.insertText("foo");
437     QCOMPARE(cursor.position(), 4);
438
439     cursor.insertList(QTextListFormat::ListCircle);
440     QCOMPARE(cursor.position(), 5);
441     cursor.insertText("something");
442     QCOMPARE(cursor.position(), 14);
443
444     cursor.movePosition(QTextCursor::PreviousCharacter);
445     QCOMPARE(cursor.position(), 13);
446
447     cursor.setPosition(2);
448     cursor.movePosition(QTextCursor::NextCharacter);
449     QCOMPARE(cursor.position(), 3);
450 }
451
452 void tst_QTextCursor::navigation9()
453 {
454     cursor.insertText("Hello  &-=+\t   World");
455     cursor.movePosition(QTextCursor::PreviousWord);
456     QCOMPARE(cursor.position(), 15);
457     cursor.movePosition(QTextCursor::PreviousWord);
458     QCOMPARE(cursor.position(), 7);
459     cursor.movePosition(QTextCursor::PreviousWord);
460     QCOMPARE(cursor.position(), 0);
461     cursor.movePosition(QTextCursor::NextWord);
462     QCOMPARE(cursor.position(), 7);
463     cursor.movePosition(QTextCursor::NextWord);
464     QCOMPARE(cursor.position(), 15);
465 }
466
467 void tst_QTextCursor::navigation10()
468 {
469     doc->setHtml("<html><p>just a simple paragraph.</p>"
470         "<table>"
471           "<tr><td>Cell number 1</td><td>another cell</td><td></td><td>previous</br>is</br>empty</td></tr>"
472           "<tr><td>row 2</td><td colspan=\"2\">foo bar</td><td>last cell</td></tr>"
473           "<tr><td colspan=\"3\">row 3</td><td>a</td></tr>"
474         "</table></html");
475     QCOMPARE(cursor.position(), 101); // end of document
476     cursor.setPosition(0);
477     QCOMPARE(cursor.position(), 0);
478     bool ok = cursor.movePosition(QTextCursor::EndOfLine);
479     QVERIFY(ok);
480     QCOMPARE(cursor.position(), 24);
481     ok = cursor.movePosition(QTextCursor::NextBlock);
482     QCOMPARE(cursor.position(), 25); // cell 1
483     ok = cursor.movePosition(QTextCursor::NextCell);
484     QVERIFY(ok);
485     QCOMPARE(cursor.position(), 39); // another..
486     ok = cursor.movePosition(QTextCursor::NextCell);
487     QVERIFY(ok);
488     QCOMPARE(cursor.position(), 52); // empty
489     ok = cursor.movePosition(QTextCursor::NextCell);
490     QVERIFY(ok);
491     QCOMPARE(cursor.position(), 53); // last on row 1
492     ok = cursor.movePosition(QTextCursor::NextCell);
493     QVERIFY(ok);
494     QCOMPARE(cursor.position(), 69); // row 2
495     ok = cursor.movePosition(QTextCursor::NextCell);
496     QVERIFY(ok);
497     QCOMPARE(cursor.position(), 75);
498     ok = cursor.movePosition(QTextCursor::NextCell);
499     QVERIFY(ok);
500     QCOMPARE(cursor.position(), 83);
501     ok = cursor.movePosition(QTextCursor::NextCell);
502     QVERIFY(ok);
503     QCOMPARE(cursor.position(), 93); // row 3
504     ok = cursor.movePosition(QTextCursor::NextCell);
505     QVERIFY(ok);
506     QCOMPARE(cursor.position(), 99);
507     ok = cursor.movePosition(QTextCursor::NextCell);
508     QVERIFY(ok == false);
509     QCOMPARE(cursor.position(), 99); // didn't move.
510     QVERIFY(cursor.currentTable());
511
512     // same thing in reverse...
513     ok = cursor.movePosition(QTextCursor::PreviousCell);
514     QVERIFY(ok);
515     QCOMPARE(cursor.position(), 93);
516     ok = cursor.movePosition(QTextCursor::PreviousCell);
517     QVERIFY(ok);
518     QCOMPARE(cursor.position(), 83);
519     ok = cursor.movePosition(QTextCursor::PreviousCell);
520     QVERIFY(ok);
521     QCOMPARE(cursor.position(), 75);
522     ok = cursor.movePosition(QTextCursor::PreviousCell);
523     QVERIFY(ok);
524     QCOMPARE(cursor.position(), 69);
525     ok = cursor.movePosition(QTextCursor::PreviousCell);
526     QVERIFY(ok);
527     QCOMPARE(cursor.position(), 53);
528     ok = cursor.movePosition(QTextCursor::PreviousCell);
529     QVERIFY(ok);
530     QCOMPARE(cursor.position(), 52);
531     ok = cursor.movePosition(QTextCursor::PreviousCell);
532     QVERIFY(ok);
533     QCOMPARE(cursor.position(), 39);
534     ok = cursor.movePosition(QTextCursor::PreviousCell);
535     QVERIFY(ok);
536     QCOMPARE(cursor.position(), 25);
537     ok = cursor.movePosition(QTextCursor::PreviousCell);
538     QVERIFY(!ok);
539     QCOMPARE(cursor.position(), 25); // can't leave the table
540
541     ok = cursor.movePosition(QTextCursor::NextRow);
542     QVERIFY(ok);
543     QCOMPARE(cursor.position(), 69);
544     ok = cursor.movePosition(QTextCursor::NextRow);
545     QVERIFY(ok);
546     QCOMPARE(cursor.position(), 93);
547     ok = cursor.movePosition(QTextCursor::NextRow);
548     QVERIFY(!ok);
549     QCOMPARE(cursor.position(), 93); // didn't move
550
551     ok = cursor.movePosition(QTextCursor::PreviousRow);
552     QVERIFY(ok);
553     QCOMPARE(cursor.position(), 83); // last col in row 2
554     ok = cursor.movePosition(QTextCursor::PreviousRow);
555     QVERIFY(ok);
556     QCOMPARE(cursor.position(), 53); // last col in row 1
557     ok = cursor.movePosition(QTextCursor::PreviousRow);
558     QVERIFY(!ok);
559     QCOMPARE(cursor.position(), 53);
560
561     // test usecase of jumping over a cell
562     doc->clear();
563     doc->setHtml("<html><table>tr><td rowspan=\"2\">a</td><td>b</td></tr><tr><td>c</td></tr></table></html>");
564     cursor.setPosition(1); // a
565     ok = cursor.movePosition(QTextCursor::NextCell);
566     QVERIFY(ok);
567     QCOMPARE(cursor.position(), 3); // b
568     ok = cursor.movePosition(QTextCursor::NextCell);
569     QVERIFY(ok);
570     QCOMPARE(cursor.position(), 5); // c
571     ok = cursor.movePosition(QTextCursor::PreviousCell);
572     QVERIFY(ok);
573     QCOMPARE(cursor.position(), 3); // b
574     ok = cursor.movePosition(QTextCursor::PreviousCell);
575     QVERIFY(ok);
576     QCOMPARE(cursor.position(), 1); // a
577 }
578
579 void tst_QTextCursor::insertBlock()
580 {
581     QTextBlockFormat fmt;
582     fmt.setTopMargin(100);
583     cursor.insertBlock(fmt);
584     QVERIFY(cursor.position() == 1);
585     QVERIFY(cursor.blockFormat() == fmt);
586 }
587
588 void tst_QTextCursor::insertWithBlockSeparator1()
589 {
590     QString text = "Hello" + QString(QChar::ParagraphSeparator) + "World";
591
592     cursor.insertText(text);
593
594     cursor.movePosition(QTextCursor::PreviousBlock);
595     QVERIFY(cursor.position() == 0);
596
597     cursor.movePosition(QTextCursor::NextBlock);
598     QVERIFY(cursor.position() == 6);
599 }
600
601 void tst_QTextCursor::insertWithBlockSeparator2()
602 {
603     cursor.insertText(QString(QChar::ParagraphSeparator));
604     QVERIFY(cursor.position() == 1);
605 }
606
607 void tst_QTextCursor::insertWithBlockSeparator3()
608 {
609     cursor.insertText(QString(QChar::ParagraphSeparator) + "Hi" + QString(QChar::ParagraphSeparator));
610     QVERIFY(cursor.position() == 4);
611 }
612
613 void tst_QTextCursor::insertWithBlockSeparator4()
614 {
615     cursor.insertText(QString(QChar::ParagraphSeparator) + QString(QChar::ParagraphSeparator));
616     QVERIFY(cursor.position() == 2);
617 }
618
619 void tst_QTextCursor::clearObjectType1()
620 {
621     cursor.insertImage("test.png");
622     QVERIFY(cursor.charFormat().isValid());
623     QVERIFY(cursor.charFormat().isImageFormat());
624     cursor.insertText("Hey");
625     QVERIFY(cursor.charFormat().isValid());
626     QVERIFY(!cursor.charFormat().isImageFormat());
627 }
628
629 void tst_QTextCursor::clearObjectType2()
630 {
631     cursor.insertImage("test.png");
632     QVERIFY(cursor.charFormat().isValid());
633     QVERIFY(cursor.charFormat().isImageFormat());
634     cursor.insertBlock();
635     QVERIFY(cursor.charFormat().isValid());
636     QVERIFY(!cursor.charFormat().isImageFormat());
637 }
638
639 void tst_QTextCursor::clearObjectType3()
640 {
641     // like clearObjectType2 but tests different insertBlock overload
642     cursor.insertImage("test.png");
643     QVERIFY(cursor.charFormat().isValid());
644     QVERIFY(cursor.charFormat().isImageFormat());
645     QTextBlockFormat bfmt;
646     bfmt.setAlignment(Qt::AlignRight);
647     cursor.insertBlock(bfmt);
648     QVERIFY(cursor.charFormat().isValid());
649     QVERIFY(!cursor.charFormat().isImageFormat());
650 }
651
652 void tst_QTextCursor::comparisonOperators1()
653 {
654     cursor.insertText("Hello World");
655
656     cursor.movePosition(QTextCursor::PreviousWord);
657
658     QTextCursor startCursor = cursor;
659     startCursor.movePosition(QTextCursor::Start);
660
661     QVERIFY(startCursor < cursor);
662
663     QTextCursor midCursor = startCursor;
664     midCursor.movePosition(QTextCursor::NextWord);
665
666     QVERIFY(midCursor <= cursor);
667     QVERIFY(midCursor == cursor);
668     QVERIFY(midCursor >= cursor);
669
670     QVERIFY(midCursor > startCursor);
671
672     QVERIFY(midCursor != startCursor);
673     QVERIFY(!(midCursor == startCursor));
674
675     QTextCursor nullCursor;
676
677     QVERIFY(!(startCursor < nullCursor));
678     QVERIFY(!(nullCursor < nullCursor));
679     QVERIFY(nullCursor < startCursor);
680
681     QVERIFY(nullCursor <= startCursor);
682     QVERIFY(!(startCursor <= nullCursor));
683
684     QVERIFY(!(nullCursor >= startCursor));
685     QVERIFY(startCursor >= nullCursor);
686
687     QVERIFY(!(nullCursor > startCursor));
688     QVERIFY(!(nullCursor > nullCursor));
689     QVERIFY(startCursor > nullCursor);
690 }
691
692 void tst_QTextCursor::comparisonOperators2()
693 {
694     QTextDocument doc1;
695     QTextDocument doc2;
696
697     QTextCursor cursor1(&doc1);
698     QTextCursor cursor2(&doc2);
699
700     QVERIFY(cursor1 != cursor2);
701     QVERIFY(cursor1 == QTextCursor(&doc1));
702 }
703
704 void tst_QTextCursor::selection1()
705 {
706     cursor.insertText("Hello World");
707
708     cursor.setPosition(0);
709     cursor.clearSelection();
710     cursor.setPosition(4, QTextCursor::KeepAnchor);
711
712     QCOMPARE(cursor.selectionStart(), 0);
713     QCOMPARE(cursor.selectionEnd(), 4);
714 }
715
716 void tst_QTextCursor::dontCopyTableAttributes()
717 {
718     /* when pressing 'enter' inside a cell it shouldn't
719      * enlarge the table by adding another cell but just
720      * extend the cell */
721     QTextTable *table = cursor.insertTable(2, 2);
722     QVERIFY(cursor == table->cellAt(0, 0).firstCursorPosition());
723     cursor.insertBlock();
724     QCOMPARE(table->columns(), 2);
725 }
726
727 void tst_QTextCursor::checkFrame1()
728 {
729     QVERIFY(cursor.position() == 0);
730     QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
731     QVERIFY(frame != 0);
732
733     QTextFrame *root = frame->parentFrame();
734     QVERIFY(root != 0);
735
736     QVERIFY(frame->firstPosition() == 1);
737     QVERIFY(frame->lastPosition() == 1);
738     QVERIFY(frame->parentFrame() != 0);
739     QVERIFY(root->childFrames().size() == 1);
740
741     QVERIFY(cursor.position() == 1);
742     QVERIFY(cursor.selectionStart() == 1);
743     QVERIFY(cursor.selectionEnd() == 1);
744
745     doc->undo();
746
747     QVERIFY(!frame);
748     QVERIFY(root->childFrames().size() == 0);
749
750     QVERIFY(cursor.position() == 0);
751     QVERIFY(cursor.selectionStart() == 0);
752     QVERIFY(cursor.selectionEnd() == 0);
753
754     doc->redo();
755
756     frame = doc->frameAt(1);
757
758     QVERIFY(frame);
759     QVERIFY(frame->firstPosition() == 1);
760     QVERIFY(frame->lastPosition() == 1);
761     QVERIFY(frame->parentFrame() != 0);
762     QVERIFY(root->childFrames().size() == 1);
763
764     QVERIFY(cursor.position() == 1);
765     QVERIFY(cursor.selectionStart() == 1);
766     QVERIFY(cursor.selectionEnd() == 1);
767
768 //     cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
769 //     QVERIFY(cursor.position() == 2);
770 //     QVERIFY(cursor.selectionStart() == 0);
771 //     QVERIFY(cursor.selectionEnd() == 2);
772 }
773
774 void tst_QTextCursor::checkFrame2()
775 {
776     QVERIFY(cursor.position() == 0);
777     cursor.insertText("A");
778     QVERIFY(cursor.position() == 1);
779     cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
780
781     QPointer<QTextFrame> frame = cursor.insertFrame(QTextFrameFormat());
782     QTextFrame *root = frame->parentFrame();
783
784     QVERIFY(frame->firstPosition() == 1);
785     QVERIFY(frame->lastPosition() == 2);
786     QVERIFY(frame->parentFrame() != 0);
787     QVERIFY(root->childFrames().size() == 1);
788
789     QVERIFY(cursor.position() == 1);
790     QVERIFY(cursor.selectionStart() == 1);
791     QVERIFY(cursor.selectionEnd() == 2);
792
793     doc->undo();
794
795     QVERIFY(!frame);
796     QVERIFY(root->childFrames().size() == 0);
797
798     QVERIFY(cursor.position() == 0);
799     QVERIFY(cursor.selectionStart() == 0);
800     QVERIFY(cursor.selectionEnd() == 1);
801
802     doc->redo();
803
804     frame = doc->frameAt(1);
805
806     QVERIFY(frame);
807     QVERIFY(frame->firstPosition() == 1);
808     QVERIFY(frame->lastPosition() == 2);
809     QVERIFY(frame->parentFrame() != 0);
810     QVERIFY(root->childFrames().size() == 1);
811
812     QVERIFY(cursor.position() == 1);
813     QVERIFY(cursor.selectionStart() == 1);
814     QVERIFY(cursor.selectionEnd() == 2);
815
816     cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
817     QVERIFY(cursor.position() == 0);
818     QVERIFY(cursor.selectionStart() == 0);
819     QVERIFY(cursor.selectionEnd() == 3);
820 }
821
822 void tst_QTextCursor::insertBlockToUseCharFormat()
823 {
824     QTextCharFormat fmt;
825     fmt.setForeground(Qt::blue);
826     cursor.insertText("Hello", fmt);
827     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
828
829     cursor.insertBlock();
830     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::blue));
831
832     fmt.setForeground(Qt::red);
833     cursor.insertText("Hello\nWorld", fmt);
834     cursor.insertText("Blah");
835     QCOMPARE(cursor.charFormat().foreground().color(), QColor(Qt::red));
836
837     // ### we might want a testcase for createTable, too, as it calls insertBlock, too,
838     // and we might want to have the char format copied (the one that gets inserted
839     // as table separators, that are undeletable)
840 }
841
842 void tst_QTextCursor::tableMovement()
843 {
844     QVERIFY(cursor.position() == 0);
845     cursor.insertText("AA");
846     QVERIFY(cursor.position() == 2);
847     cursor.movePosition(QTextCursor::Left);
848
849     cursor.insertTable(3, 3);
850     QCOMPARE(cursor.position(), 2);
851
852     cursor.movePosition(QTextCursor::Down);
853     QCOMPARE(cursor.position(), 5);
854
855     cursor.movePosition(QTextCursor::Right);
856     QCOMPARE(cursor.position(), 6);
857
858     cursor.movePosition(QTextCursor::Up);
859     QCOMPARE(cursor.position(), 3);
860
861     cursor.movePosition(QTextCursor::Right);
862     QCOMPARE(cursor.position(), 4);
863
864     cursor.movePosition(QTextCursor::Right);
865     QCOMPARE(cursor.position(), 5);
866
867     cursor.movePosition(QTextCursor::Up);
868     QCOMPARE(cursor.position(), 2);
869
870     cursor.movePosition(QTextCursor::Up);
871     QCOMPARE(cursor.position(), 0);
872
873 }
874
875 void tst_QTextCursor::selectionsInTable()
876 {
877     QTextTable *table = cursor.insertTable(2, 2);
878     table->cellAt(0, 0).firstCursorPosition().insertText("First");
879     table->cellAt(0, 1).firstCursorPosition().insertText("Second");
880     table->cellAt(1, 0).firstCursorPosition().insertText("Third");
881     table->cellAt(1, 1).firstCursorPosition().insertText("Fourth");
882
883     cursor = table->cellAt(0, 0).lastCursorPosition();
884     QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
885     QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
886
887     cursor = table->cellAt(1, 0).lastCursorPosition();
888     QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor));
889     QVERIFY(cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor) == false);
890
891     cursor = table->cellAt(0, 1).firstCursorPosition();
892     QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
893     QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
894
895     cursor = table->cellAt(1, 1).firstCursorPosition();
896     QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor));
897     QVERIFY(cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor) == false);
898 }
899
900 void tst_QTextCursor::selectedText()
901 {
902     cursor.insertText("Hello World");
903     cursor.movePosition(QTextCursor::Start);
904     cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
905
906     QCOMPARE(cursor.selectedText(), QString("Hello World"));
907 }
908
909 void tst_QTextCursor::insertBlockShouldRemoveSelection()
910 {
911     cursor.insertText("Hello World");
912     cursor.movePosition(QTextCursor::Start);
913     cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
914
915     QVERIFY(cursor.hasSelection());
916     QCOMPARE(cursor.selectedText(), QString("Hello"));
917
918     cursor.insertBlock();
919
920     QVERIFY(!cursor.hasSelection());
921     QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
922 }
923
924 void tst_QTextCursor::insertBlockShouldRemoveSelection2()
925 {
926     cursor.insertText("Hello World");
927     cursor.movePosition(QTextCursor::Start);
928     cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
929
930     QVERIFY(cursor.hasSelection());
931     QCOMPARE(cursor.selectedText(), QString("Hello"));
932
933     QTextBlockFormat fmt = cursor.blockFormat();
934     cursor.insertBlock(fmt);
935
936     QVERIFY(!cursor.hasSelection());
937     QVERIFY(doc->toPlainText().indexOf("Hello") == -1);
938 }
939
940 void tst_QTextCursor::mergeCellShouldUpdateSelection()
941 {
942     QTextTable *table = cursor.insertTable(4, 4);
943     cursor.setPosition(table->cellAt(0, 0).firstPosition());
944     cursor.setPosition(table->cellAt(3, 0).firstPosition(), QTextCursor::KeepAnchor); // aka bottom left
945     int firstRow, numRows, firstColumn, numColumns;
946     cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns);
947     QCOMPARE(firstRow, 0);
948     QCOMPARE(numRows, 4);
949     QCOMPARE(firstColumn, 0);
950     QCOMPARE(numColumns, 1);
951
952     table->removeColumns(firstColumn, numColumns);
953
954     QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
955     QCOMPARE(cursor.position(), table->cellAt(0, 0).firstPosition());
956     QCOMPARE(cursor.position(), cursor.anchor()); // empty. I don't really care where it ends up.
957
958     // prepare for another test with multiple cursors.
959     // note we have a 4 rows, 3 cols table now.
960     cursor.setPosition(table->cellAt(0, 0).firstPosition());
961     cursor.setPosition(table->cellAt(0, 2).firstPosition(), QTextCursor::KeepAnchor);
962
963     // now create a selection of a whole row.
964     QTextCursor c2 = table->cellAt(2, 0).firstCursorPosition();
965     c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
966
967     // just for good measure, another one for a block of cells.
968     QTextCursor c3 = table->cellAt(2, 1).firstCursorPosition();
969     c3.setPosition(table->cellAt(3, 2).firstPosition(), QTextCursor::KeepAnchor);
970
971     table->removeRows(2, 1);
972
973     QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
974     QCOMPARE(cursor.position(), table->cellAt(0, 2).firstPosition());
975
976     QCOMPARE(c2.position(), c2.anchor()); // empty. I don't really care where it ends up.
977
978     QCOMPARE(c3.anchor(), table->cellAt(2, 1).firstPosition());
979     QCOMPARE(c3.position(), table->cellAt(2, 2).firstPosition());
980
981
982     // prepare for another test where we remove a column
983     // note we have a 3 rows, 3 cols table now.
984     cursor.setPosition(table->cellAt(0, 0).firstPosition());
985     cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
986
987     c2.setPosition(table->cellAt(0, 1).firstPosition());
988     c2.setPosition(table->cellAt(2, 2).firstPosition(), QTextCursor::KeepAnchor);
989
990     table->removeColumns(1, 1);
991
992     QCOMPARE(cursor.anchor(), table->cellAt(0, 0).firstPosition());
993     QCOMPARE(cursor.position(), table->cellAt(2, 0).firstPosition());
994
995     QCOMPARE(c2.anchor(), table->cellAt(0, 1).firstPosition());
996     QCOMPARE(c2.position(), table->cellAt(2, 1).firstPosition());
997
998     // test for illegal cursor positions.
999     // note we have a 3 rows, 2 cols table now.
1000     cursor.setPosition(table->cellAt(2, 0).firstPosition());
1001     cursor.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
1002
1003     c2.setPosition(table->cellAt(0, 0).firstPosition());
1004     c2.setPosition(table->cellAt(2, 1).firstPosition(), QTextCursor::KeepAnchor);
1005
1006     c3.setPosition(table->cellAt(2, 1).firstPosition());
1007
1008     table->removeRows(2, 1);
1009
1010     QCOMPARE(cursor.anchor(), table->cellAt(1, 1).lastPosition()+1);
1011     QCOMPARE(cursor.position(), cursor.anchor());
1012
1013     QCOMPARE(c2.anchor(), table->cellAt(0, 0).firstPosition());
1014     QCOMPARE(c2.position(), table->cellAt(1, 1).firstPosition());
1015
1016     QCOMPARE(c3.anchor(), table->cellAt(1, 1).firstPosition());
1017     QCOMPARE(c3.position(), table->cellAt(1, 1).firstPosition());
1018 }
1019
1020 void tst_QTextCursor::joinPreviousEditBlock()
1021 {
1022     cursor.beginEditBlock();
1023     cursor.insertText("Hello");
1024     cursor.insertText("World");
1025     cursor.endEditBlock();
1026     QVERIFY(doc->toPlainText().startsWith("HelloWorld"));
1027
1028     cursor.joinPreviousEditBlock();
1029     cursor.insertText("Hey");
1030     cursor.endEditBlock();
1031     QVERIFY(doc->toPlainText().startsWith("HelloWorldHey"));
1032
1033     doc->undo();
1034     QVERIFY(!doc->toPlainText().contains("HelloWorldHey"));
1035 }
1036
1037 void tst_QTextCursor::setBlockFormatInTable()
1038 {
1039     // someone reported this on qt4-preview-feedback
1040     QTextBlockFormat fmt;
1041     fmt.setBackground(Qt::blue);
1042     cursor.setBlockFormat(fmt);
1043
1044     QTextTable *table = cursor.insertTable(2, 2);
1045     cursor = table->cellAt(0, 0).firstCursorPosition();
1046     fmt.setBackground(Qt::red);
1047     cursor.setBlockFormat(fmt);
1048
1049     cursor.movePosition(QTextCursor::Start);
1050     QVERIFY(cursor.blockFormat().background().color() == Qt::blue);
1051 }
1052
1053 void tst_QTextCursor::blockCharFormat2()
1054 {
1055     QTextCharFormat fmt;
1056     fmt.setForeground(Qt::green);
1057     cursor.mergeBlockCharFormat(fmt);
1058
1059     fmt.setForeground(Qt::red);
1060
1061     cursor.insertText("Test", fmt);
1062     cursor.movePosition(QTextCursor::Start);
1063     cursor.insertText("Red");
1064     cursor.movePosition(QTextCursor::PreviousCharacter);
1065     QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
1066 }
1067
1068 void tst_QTextCursor::blockCharFormat3()
1069 {
1070     QVERIFY(cursor.atBlockStart());
1071     QVERIFY(cursor.atBlockEnd());
1072     QVERIFY(cursor.atStart());
1073
1074     QTextCharFormat fmt;
1075     fmt.setForeground(Qt::green);
1076     cursor.setBlockCharFormat(fmt);
1077     cursor.insertText("Test");
1078     cursor.movePosition(QTextCursor::Start);
1079     cursor.movePosition(QTextCursor::NextCharacter);
1080     QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
1081
1082     cursor.movePosition(QTextCursor::Start);
1083     QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
1084
1085     fmt.setForeground(Qt::red);
1086     cursor.setBlockCharFormat(fmt);
1087     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
1088
1089     cursor.movePosition(QTextCursor::End);
1090     cursor.movePosition(QTextCursor::Start);
1091     QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
1092
1093     cursor.insertText("Test");
1094     QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
1095
1096     cursor.select(QTextCursor::Document);
1097     cursor.removeSelectedText();
1098     QVERIFY(cursor.atBlockStart());
1099     QVERIFY(cursor.atBlockEnd());
1100     QVERIFY(cursor.atStart());
1101
1102     cursor.insertText("Test");
1103     QVERIFY(cursor.charFormat().foreground().color() == Qt::red);
1104 }
1105
1106 void tst_QTextCursor::blockCharFormat()
1107 {
1108     QTextCharFormat fmt;
1109     fmt.setForeground(Qt::blue);
1110     cursor.insertBlock(QTextBlockFormat(), fmt);
1111     cursor.insertText("Hm");
1112
1113     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
1114
1115     fmt.setForeground(Qt::red);
1116
1117     cursor.setBlockCharFormat(fmt);
1118     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
1119 }
1120
1121 void tst_QTextCursor::blockCharFormatOnSelection()
1122 {
1123     QTextCharFormat fmt;
1124     fmt.setForeground(Qt::blue);
1125     cursor.insertBlock(QTextBlockFormat(), fmt);
1126
1127     fmt.setForeground(Qt::green);
1128     cursor.insertText("Hm", fmt);
1129
1130     fmt.setForeground(Qt::red);
1131     cursor.insertBlock(QTextBlockFormat(), fmt);
1132     cursor.insertText("Ah");
1133
1134     fmt.setForeground(Qt::white);
1135     cursor.insertBlock(QTextBlockFormat(), fmt);
1136     cursor.insertText("bleh");
1137
1138     cursor.movePosition(QTextCursor::Start);
1139     cursor.movePosition(QTextCursor::NextBlock);
1140     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::blue);
1141     cursor.movePosition(QTextCursor::NextBlock);
1142     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::red);
1143     cursor.movePosition(QTextCursor::NextBlock);
1144     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
1145
1146     cursor.movePosition(QTextCursor::Start);
1147     cursor.movePosition(QTextCursor::NextBlock);
1148     cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
1149
1150     fmt.setForeground(Qt::cyan);
1151     cursor.setBlockCharFormat(fmt);
1152
1153     cursor.movePosition(QTextCursor::Start);
1154     cursor.movePosition(QTextCursor::NextBlock);
1155     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
1156
1157     cursor.movePosition(QTextCursor::Right);
1158     cursor.movePosition(QTextCursor::Right);
1159     QVERIFY(cursor.charFormat().foreground().color() == Qt::green);
1160
1161     cursor.movePosition(QTextCursor::NextBlock);
1162     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::cyan);
1163
1164     cursor.movePosition(QTextCursor::NextBlock);
1165     QVERIFY(cursor.blockCharFormat().foreground().color() == Qt::white);
1166 }
1167
1168 void tst_QTextCursor::anchorInitialized1()
1169 {
1170     cursor.insertBlock();
1171     cursor = QTextCursor(cursor.block());
1172     QCOMPARE(cursor.position(), 1);
1173     QCOMPARE(cursor.anchor(), 1);
1174     QCOMPARE(cursor.selectionStart(), 1);
1175     QCOMPARE(cursor.selectionEnd(), 1);
1176 }
1177
1178 void tst_QTextCursor::anchorInitialized2()
1179 {
1180     cursor.insertBlock();
1181     cursor = QTextCursor(cursor.block().docHandle(), 1);
1182     QCOMPARE(cursor.position(), 1);
1183     QCOMPARE(cursor.anchor(), 1);
1184     QCOMPARE(cursor.selectionStart(), 1);
1185     QCOMPARE(cursor.selectionEnd(), 1);
1186 }
1187
1188 void tst_QTextCursor::anchorInitialized3()
1189 {
1190     QTextFrame *frame = cursor.insertFrame(QTextFrameFormat());
1191     cursor = QTextCursor(frame);
1192     QCOMPARE(cursor.position(), 1);
1193     QCOMPARE(cursor.anchor(), 1);
1194     QCOMPARE(cursor.selectionStart(), 1);
1195     QCOMPARE(cursor.selectionEnd(), 1);
1196 }
1197
1198 void tst_QTextCursor::selectWord()
1199 {
1200     cursor.insertText("first second     third");
1201     cursor.insertBlock();
1202     cursor.insertText("words in second paragraph");
1203
1204     cursor.setPosition(9);
1205     cursor.select(QTextCursor::WordUnderCursor);
1206     QVERIFY(cursor.hasSelection());
1207     QCOMPARE(cursor.selectionStart(), 6);
1208     QCOMPARE(cursor.selectionEnd(), 12);
1209
1210     cursor.setPosition(5);
1211     cursor.select(QTextCursor::WordUnderCursor);
1212     QVERIFY(cursor.hasSelection());
1213     QCOMPARE(cursor.selectionStart(), 0);
1214     QCOMPARE(cursor.selectionEnd(), 5);
1215
1216     cursor.setPosition(6);
1217     cursor.select(QTextCursor::WordUnderCursor);
1218     QVERIFY(cursor.hasSelection());
1219     QCOMPARE(cursor.selectionStart(), 6);
1220     QCOMPARE(cursor.selectionEnd(), 12);
1221
1222     cursor.setPosition(14);
1223     cursor.select(QTextCursor::WordUnderCursor);
1224     QVERIFY(cursor.hasSelection());
1225     QCOMPARE(cursor.selectionStart(), 6);
1226     QCOMPARE(cursor.selectionEnd(), 12);
1227
1228     cursor.movePosition(QTextCursor::Start);
1229     cursor.select(QTextCursor::WordUnderCursor);
1230     QVERIFY(cursor.hasSelection());
1231     QCOMPARE(cursor.selectionStart(), 0);
1232     QCOMPARE(cursor.selectionEnd(), 5);
1233
1234     cursor.movePosition(QTextCursor::EndOfBlock);
1235     cursor.select(QTextCursor::WordUnderCursor);
1236     QVERIFY(cursor.hasSelection());
1237     QCOMPARE(cursor.selectionStart(), 17);
1238     QCOMPARE(cursor.selectionEnd(), 22);
1239 }
1240
1241 void tst_QTextCursor::selectWordWithSeparators_data()
1242 {
1243     QTest::addColumn<QString>("text");
1244     QTest::addColumn<int>("initialPosition");
1245     QTest::addColumn<QString>("expectedSelectedText");
1246
1247     QTest::newRow("dereference") << QString::fromLatin1("foo->bar()") << 1 << QString::fromLatin1("foo");
1248     QTest::newRow("funcsignature") << QString::fromLatin1("bar(int x);") << 1 << QString::fromLatin1("bar");
1249     QTest::newRow("def") << QString::fromLatin1("foo *f;") << 1 << QString::fromLatin1("foo");
1250 }
1251
1252 void tst_QTextCursor::selectWordWithSeparators()
1253 {
1254     QFETCH(QString, text);
1255     QFETCH(int, initialPosition);
1256     QFETCH(QString, expectedSelectedText);
1257
1258     cursor.insertText(text);
1259     cursor.setPosition(initialPosition);
1260     cursor.select(QTextCursor::WordUnderCursor);
1261
1262     QCOMPARE(cursor.selectedText(), expectedSelectedText);
1263 }
1264
1265 void tst_QTextCursor::startOfWord()
1266 {
1267     cursor.insertText("first     second");
1268     cursor.setPosition(7);
1269     cursor.movePosition(QTextCursor::StartOfWord);
1270     QCOMPARE(cursor.position(), 0);
1271 }
1272
1273 void tst_QTextCursor::selectBlock()
1274 {
1275     cursor.insertText("foobar");
1276     QTextBlockFormat blockFmt;
1277     blockFmt.setAlignment(Qt::AlignHCenter);
1278     cursor.insertBlock(blockFmt);
1279     cursor.insertText("blah");
1280     cursor.insertBlock(QTextBlockFormat());
1281
1282     cursor.movePosition(QTextCursor::PreviousBlock);
1283     QCOMPARE(cursor.block().text(), QString("blah"));
1284
1285     cursor.select(QTextCursor::BlockUnderCursor);
1286     QVERIFY(cursor.hasSelection());
1287
1288     QTextDocumentFragment fragment(cursor);
1289     doc->clear();
1290     cursor.insertFragment(fragment);
1291     QCOMPARE(blockCount(), 2);
1292
1293     cursor.movePosition(QTextCursor::Start);
1294     cursor.movePosition(QTextCursor::NextBlock);
1295     QVERIFY(cursor.blockFormat().alignment() == Qt::AlignHCenter);
1296     QCOMPARE(cursor.block().text(), QString("blah"));
1297 }
1298
1299 void tst_QTextCursor::selectVisually()
1300 {
1301     cursor.insertText("Foo\nlong line which is probably going to be cut in two when shown in a widget\nparagraph 3\n");
1302
1303     cursor.setPosition(6); // somewhere in the long paragraph.
1304     cursor.select(QTextCursor::LineUnderCursor);
1305     // since we are not yet layed-out, we expect the whole paragraph to be selected.
1306     QCOMPARE(cursor.position(), 77);
1307     QCOMPARE(cursor.anchor(), 4);
1308 }
1309
1310 void tst_QTextCursor::insertText()
1311 {
1312     QString txt = "Foo\nBar\r\nMeep";
1313     txt += QChar::LineSeparator;
1314     txt += "Baz";
1315     txt += QChar::ParagraphSeparator;
1316     txt += "yoyodyne";
1317     cursor.insertText(txt);
1318     QCOMPARE(blockCount(), 4);
1319     cursor.movePosition(QTextCursor::Start);
1320     QCOMPARE(cursor.block().text(), QString("Foo"));
1321     cursor.movePosition(QTextCursor::NextBlock);
1322     QCOMPARE(cursor.block().text(), QString("Bar"));
1323     cursor.movePosition(QTextCursor::NextBlock);
1324     QCOMPARE(cursor.block().text(), QString(QString("Meep") + QChar(QChar::LineSeparator) + QString("Baz")));
1325     cursor.movePosition(QTextCursor::NextBlock);
1326     QCOMPARE(cursor.block().text(), QString("yoyodyne"));
1327 }
1328
1329 void tst_QTextCursor::insertFragmentShouldUseCurrentCharFormat()
1330 {
1331     QTextDocumentFragment fragment = QTextDocumentFragment::fromPlainText("Hello World");
1332     QTextCharFormat fmt;
1333     fmt.setFontUnderline(true);
1334
1335     cursor.clearSelection();
1336     cursor.setCharFormat(fmt);
1337     cursor.insertFragment(fragment);
1338     cursor.movePosition(QTextCursor::Start);
1339     cursor.movePosition(QTextCursor::NextCharacter);
1340     QVERIFY(cursor.charFormat() == fmt);
1341 }
1342
1343 int tst_QTextCursor::blockCount()
1344 {
1345     int cnt = 0;
1346     for (QTextBlock blk = doc->begin(); blk.isValid(); blk = blk.next())
1347         ++cnt;
1348     return cnt;
1349 }
1350
1351 void tst_QTextCursor::endOfLine()
1352 {
1353     doc->setPageSize(QSizeF(100000, INT_MAX));
1354
1355     QString text("First Line    \nSecond Line  ");
1356     text.replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
1357     cursor.insertText(text);
1358
1359     // ensure layouted
1360     doc->documentLayout()->documentSize();
1361
1362     cursor.movePosition(QTextCursor::Start);
1363
1364     QCOMPARE(cursor.block().layout()->lineCount(), 2);
1365
1366     cursor.movePosition(QTextCursor::EndOfLine);
1367     QCOMPARE(cursor.position(), 14);
1368     cursor.movePosition(QTextCursor::NextCharacter);
1369     QCOMPARE(cursor.position(), 15);
1370     cursor.movePosition(QTextCursor::EndOfLine);
1371     QCOMPARE(cursor.position(), 28);
1372 }
1373
1374 class CursorListener : public QObject
1375 {
1376     Q_OBJECT
1377 public:
1378     CursorListener(QTextCursor *_cursor) : lastRecordedPosition(-1), lastRecordedAnchor(-1), recordingCount(0), cursor(_cursor) {}
1379
1380     int lastRecordedPosition;
1381     int lastRecordedAnchor;
1382     int recordingCount;
1383
1384 public slots:
1385     void recordCursorPosition()
1386     {
1387         lastRecordedPosition = cursor->position();
1388         lastRecordedAnchor = cursor->anchor();
1389         ++recordingCount;
1390     }
1391
1392     void selectAllContents()
1393     {
1394         // Only test the first time
1395         if (!recordingCount) {
1396             recordingCount++;
1397             cursor->select(QTextCursor::Document);
1398             lastRecordedPosition = cursor->position();
1399             lastRecordedAnchor = cursor->anchor();
1400         }
1401     }
1402
1403 private:
1404     QTextCursor *cursor;
1405 };
1406
1407 void tst_QTextCursor::editBlocksDuringRemove()
1408 {
1409     CursorListener listener(&cursor);
1410
1411     cursor.insertText("Hello World");
1412     cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
1413     QCOMPARE(cursor.selectedText(), QString("Hello World"));
1414
1415     connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(recordCursorPosition()));
1416     listener.recordingCount = 0;
1417     cursor.deleteChar();
1418
1419     QCOMPARE(listener.recordingCount, 1);
1420     QCOMPARE(listener.lastRecordedPosition, 0);
1421     QCOMPARE(listener.lastRecordedAnchor, 0);
1422
1423     QVERIFY(doc->toPlainText().isEmpty());
1424 }
1425
1426 void tst_QTextCursor::selectAllDuringRemove()
1427 {
1428     CursorListener listener(&cursor);
1429
1430     cursor.insertText("Hello World");
1431     cursor.movePosition(QTextCursor::End);
1432
1433     connect(doc, SIGNAL(contentsChanged()), &listener, SLOT(selectAllContents()));
1434     listener.recordingCount = 0;
1435     QTextCursor localCursor = cursor;
1436     localCursor.deletePreviousChar();
1437
1438     QCOMPARE(listener.lastRecordedPosition, 10);
1439     QCOMPARE(listener.lastRecordedAnchor, 0);
1440 }
1441
1442 void tst_QTextCursor::update_data()
1443 {
1444     QTest::addColumn<QString>("text");
1445     QTest::addColumn<int>("position");
1446     QTest::addColumn<int>("anchor");
1447     QTest::addColumn<int>("modifyPosition");
1448     QTest::addColumn<int>("modifyAnchor");
1449     QTest::addColumn<QString>("insertText");
1450     QTest::addColumn<int>("expectedPosition");
1451     QTest::addColumn<int>("expectedAnchor");
1452
1453     QString text("Hello big world");
1454     int charsToDelete = 3;
1455     QTest::newRow("removeInsideSelection")
1456         << text
1457         << /*position*/ 0
1458         << /*anchor*/ text.length()
1459         // delete 'big'
1460         << 6
1461         << 6 + charsToDelete
1462         << QString() // don't insert anything, just remove
1463         << /*expectedPosition*/ 0
1464         << /*expectedAnchor*/ text.length() - charsToDelete
1465         ;
1466
1467     text = "Hello big world";
1468     charsToDelete = 3;
1469     QTest::newRow("removeInsideSelectionWithSwappedAnchorAndPosition")
1470         << text
1471         << /*position*/ text.length()
1472         << /*anchor*/ 0
1473         // delete 'big'
1474         << 6
1475         << 6 + charsToDelete
1476         << QString() // don't insert anything, just remove
1477         << /*expectedPosition*/ text.length() - charsToDelete
1478         << /*expectedAnchor*/ 0
1479         ;
1480
1481
1482     text = "Hello big world";
1483     charsToDelete = 3;
1484     QString textToInsert("small");
1485     QTest::newRow("replaceInsideSelection")
1486         << text
1487         << /*position*/ 0
1488         << /*anchor*/ text.length()
1489         // delete 'big' ...
1490         << 6
1491         << 6 + charsToDelete
1492         << textToInsert // ... and replace 'big' with 'small'
1493         << /*expectedPosition*/ 0
1494         << /*expectedAnchor*/ text.length() - charsToDelete + textToInsert.length()
1495         ;
1496
1497     text = "Hello big world";
1498     charsToDelete = 3;
1499     textToInsert = "small";
1500     QTest::newRow("replaceInsideSelectionWithSwappedAnchorAndPosition")
1501         << text
1502         << /*position*/ text.length()
1503         << /*anchor*/ 0
1504         // delete 'big' ...
1505         << 6
1506         << 6 + charsToDelete
1507         << textToInsert // ... and replace 'big' with 'small'
1508         << /*expectedPosition*/ text.length() - charsToDelete + textToInsert.length()
1509         << /*expectedAnchor*/ 0
1510         ;
1511
1512
1513     text = "Hello big world";
1514     charsToDelete = 3;
1515     QTest::newRow("removeBeforeSelection")
1516         << text
1517         << /*position*/ text.length() - 5
1518         << /*anchor*/ text.length()
1519         // delete 'big'
1520         << 6
1521         << 6 + charsToDelete
1522         << QString() // don't insert anything, just remove
1523         << /*expectedPosition*/ text.length() - 5 - charsToDelete
1524         << /*expectedAnchor*/ text.length() - charsToDelete
1525         ;
1526
1527     text = "Hello big world";
1528     charsToDelete = 3;
1529     QTest::newRow("removeAfterSelection")
1530         << text
1531         << /*position*/ 0
1532         << /*anchor*/ 4
1533         // delete 'big'
1534         << 6
1535         << 6 + charsToDelete
1536         << QString() // don't insert anything, just remove
1537         << /*expectedPosition*/ 0
1538         << /*expectedAnchor*/ 4
1539         ;
1540
1541 }
1542
1543 void tst_QTextCursor::update()
1544 {
1545     QFETCH(QString, text);
1546
1547     doc->setPlainText(text);
1548
1549     QFETCH(int, position);
1550     QFETCH(int, anchor);
1551
1552     cursor.setPosition(anchor);
1553     cursor.setPosition(position, QTextCursor::KeepAnchor);
1554
1555     QCOMPARE(cursor.position(), position);
1556     QCOMPARE(cursor.anchor(), anchor);
1557
1558     QFETCH(int, modifyPosition);
1559     QFETCH(int, modifyAnchor);
1560
1561     QTextCursor modifyCursor = cursor;
1562     modifyCursor.setPosition(modifyAnchor);
1563     modifyCursor.setPosition(modifyPosition, QTextCursor::KeepAnchor);
1564
1565     QCOMPARE(modifyCursor.position(), modifyPosition);
1566     QCOMPARE(modifyCursor.anchor(), modifyAnchor);
1567
1568     QFETCH(QString, insertText);
1569     modifyCursor.insertText(insertText);
1570
1571     QFETCH(int, expectedPosition);
1572     QFETCH(int, expectedAnchor);
1573
1574     QCOMPARE(cursor.position(), expectedPosition);
1575     QCOMPARE(cursor.anchor(), expectedAnchor);
1576 }
1577
1578 void tst_QTextCursor::disallowSettingObjectIndicesOnCharFormats()
1579 {
1580     QTextCharFormat fmt;
1581     fmt.setObjectIndex(42);
1582     cursor.insertText("Hey", fmt);
1583     QCOMPARE(cursor.charFormat().objectIndex(), -1);
1584
1585     cursor.select(QTextCursor::Document);
1586     cursor.mergeCharFormat(fmt);
1587     QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
1588
1589     cursor.select(QTextCursor::Document);
1590     cursor.setCharFormat(fmt);
1591     QCOMPARE(doc->begin().begin().fragment().charFormat().objectIndex(), -1);
1592
1593     cursor.setBlockCharFormat(fmt);
1594     QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
1595
1596     cursor.movePosition(QTextCursor::End);
1597     cursor.insertBlock(QTextBlockFormat(), fmt);
1598     QCOMPARE(cursor.blockCharFormat().objectIndex(), -1);
1599
1600     doc->clear();
1601
1602     QTextTable *table = cursor.insertTable(1, 1);
1603     cursor.select(QTextCursor::Document);
1604     cursor.setCharFormat(fmt);
1605
1606     cursor = table->cellAt(0, 0).firstCursorPosition();
1607     QVERIFY(!cursor.isNull());
1608     QCOMPARE(cursor.blockCharFormat().objectIndex(), table->objectIndex());
1609 }
1610
1611 void tst_QTextCursor::blockAndColumnNumber()
1612 {
1613     QCOMPARE(QTextCursor().columnNumber(), 0);
1614     QCOMPARE(QTextCursor().blockNumber(), 0);
1615
1616     QCOMPARE(cursor.columnNumber(), 0);
1617     QCOMPARE(cursor.blockNumber(), 0);
1618     cursor.insertText("Hello");
1619     QCOMPARE(cursor.columnNumber(), 5);
1620     QCOMPARE(cursor.blockNumber(), 0);
1621
1622     cursor.insertBlock();
1623     QCOMPARE(cursor.columnNumber(), 0);
1624     QCOMPARE(cursor.blockNumber(), 1);
1625     cursor.insertText("Blah");
1626     QCOMPARE(cursor.blockNumber(), 1);
1627
1628     // trigger a layout
1629     doc->documentLayout();
1630
1631     cursor.insertBlock();
1632     QCOMPARE(cursor.columnNumber(), 0);
1633     QCOMPARE(cursor.blockNumber(), 2);
1634     cursor.insertText("Test");
1635     QCOMPARE(cursor.columnNumber(), 4);
1636     QCOMPARE(cursor.blockNumber(), 2);
1637     cursor.insertText(QString(QChar(QChar::LineSeparator)));
1638     QCOMPARE(cursor.columnNumber(), 0);
1639     QCOMPARE(cursor.blockNumber(), 2);
1640     cursor.insertText("A");
1641     QCOMPARE(cursor.columnNumber(), 1);
1642     QCOMPARE(cursor.blockNumber(), 2);
1643 }
1644
1645 void tst_QTextCursor::movePositionEndOfLine()
1646 {
1647     cursor.insertText("blah\nblah\n");
1648     // Select part of the second line ("la")
1649     cursor.setPosition(6);
1650     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2);
1651     QCOMPARE(cursor.selectedText(), QLatin1String("la"));
1652
1653     // trigger a layout
1654     doc->documentLayout();
1655
1656     // Remove "la" and append "something" to the end in one undo operation
1657     cursor.beginEditBlock();
1658     cursor.removeSelectedText();
1659     QTextCursor c2(doc);
1660     c2.setPosition(7);
1661     c2.insertText("foo"); // append to doc without touching the cursor.
1662
1663     QCOMPARE(cursor.position(), 6);
1664     cursor.movePosition(QTextCursor::EndOfLine); // in an edit block visual movement is moved to the end of the paragraph
1665     QCOMPARE(cursor.position(), 10);
1666     cursor.endEditBlock();
1667 }
1668
1669 void tst_QTextCursor::clearCells()
1670 {
1671     QTextTable *table = cursor.insertTable(3, 5);
1672     cursor.setPosition(table->cellAt(0,0).firstPosition()); // select cell 1 and cell 2
1673     cursor.setPosition(table->cellAt(0,1).firstPosition(), QTextCursor::KeepAnchor);
1674     cursor.deleteChar(); // should clear the cells, and not crash ;)
1675 }
1676
1677 void tst_QTextCursor::task244408_wordUnderCursor_data()
1678 {
1679     QTest::addColumn<QString>("input");
1680     QTest::addColumn<QString>("expected");
1681     QTest::newRow("trailingSpace") << QString::fromLatin1("foo ") << QString::fromLatin1("");
1682     QTest::newRow("noTrailingSpace") << QString::fromLatin1("foo") << QString::fromLatin1("foo");
1683 }
1684
1685 void tst_QTextCursor::task244408_wordUnderCursor()
1686 {
1687     QFETCH(QString, input);
1688     QFETCH(QString, expected);
1689     cursor.insertText(input);
1690     cursor.movePosition(QTextCursor::End);
1691     cursor.select(QTextCursor::WordUnderCursor);
1692     QCOMPARE(cursor.selectedText(), expected);
1693 }
1694
1695 void tst_QTextCursor::adjustCursorsOnInsert()
1696 {
1697     cursor.insertText("Some text before ");
1698     int posBefore = cursor.position();
1699     cursor.insertText("selected text");
1700     int posAfter = cursor.position();
1701     cursor.insertText(" some text afterwards");
1702
1703     QTextCursor selection = cursor;
1704     selection.setPosition(posBefore);
1705     selection.setPosition(posAfter, QTextCursor::KeepAnchor);
1706
1707     cursor.setPosition(posBefore-1);
1708     cursor.insertText(QLatin1String("x"));
1709     QCOMPARE(selection.anchor(), posBefore+1);
1710     QCOMPARE(selection.position(), posAfter+1);
1711     doc->undo();
1712
1713     cursor.setPosition(posBefore);
1714     cursor.insertText(QLatin1String("x"));
1715     QCOMPARE(selection.anchor(), posBefore+1);
1716     QCOMPARE(selection.position(), posAfter+1);
1717     doc->undo();
1718
1719     cursor.setPosition(posBefore+1);
1720     cursor.insertText(QLatin1String("x"));
1721     QCOMPARE(selection.anchor(), posBefore);
1722     QCOMPARE(selection.position(), posAfter+1);
1723     doc->undo();
1724
1725     cursor.setPosition(posAfter-1);
1726     cursor.insertText(QLatin1String("x"));
1727     QCOMPARE(selection.anchor(), posBefore);
1728     QCOMPARE(selection.position(), posAfter+1);
1729     doc->undo();
1730
1731     selection.setKeepPositionOnInsert(true);
1732     cursor.setPosition(posAfter);
1733     cursor.insertText(QLatin1String("x"));
1734     selection.setKeepPositionOnInsert(false);
1735     QCOMPARE(selection.anchor(), posBefore);
1736     QCOMPARE(selection.position(), posAfter);
1737     doc->undo();
1738
1739     cursor.setPosition(posAfter+1);
1740     cursor.insertText(QLatin1String("x"));
1741     QCOMPARE(selection.anchor(), posBefore);
1742     QCOMPARE(selection.position(), posAfter);
1743     doc->undo();
1744
1745     selection.setPosition(posAfter);
1746     selection.setPosition(posBefore, QTextCursor::KeepAnchor);
1747
1748     cursor.setPosition(posBefore-1);
1749     cursor.insertText(QLatin1String("x"));
1750     QCOMPARE(selection.position(), posBefore+1);
1751     QCOMPARE(selection.anchor(), posAfter+1);
1752     doc->undo();
1753
1754     cursor.setPosition(posBefore);
1755     cursor.insertText(QLatin1String("x"));
1756     QCOMPARE(selection.position(), posBefore+1);
1757     QCOMPARE(selection.anchor(), posAfter+1);
1758     doc->undo();
1759
1760     cursor.setPosition(posBefore+1);
1761     cursor.insertText(QLatin1String("x"));
1762     QCOMPARE(selection.position(), posBefore);
1763     QCOMPARE(selection.anchor(), posAfter+1);
1764     doc->undo();
1765
1766     cursor.setPosition(posAfter-1);
1767     cursor.insertText(QLatin1String("x"));
1768     QCOMPARE(selection.position(), posBefore);
1769     QCOMPARE(selection.anchor(), posAfter+1);
1770     doc->undo();
1771
1772     cursor.setPosition(posAfter);
1773     cursor.insertText(QLatin1String("x"));
1774     QCOMPARE(selection.position(), posBefore);
1775     QCOMPARE(selection.anchor(), posAfter+1);
1776     doc->undo();
1777
1778     cursor.setPosition(posAfter+1);
1779     cursor.insertText(QLatin1String("x"));
1780     QCOMPARE(selection.position(), posBefore);
1781     QCOMPARE(selection.anchor(), posAfter);
1782     doc->undo();
1783
1784 }
1785 void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo()
1786 {
1787     cursor.insertText("AAAABBBBCCCCDDDD");
1788     cursor.setPosition(12);
1789     int cursorPositionBefore = cursor.position();
1790     cursor.beginEditBlock();
1791     cursor.insertText("*");
1792     cursor.setPosition(8);
1793     cursor.insertText("*");
1794     cursor.setPosition(4);
1795     cursor.insertText("*");
1796     cursor.setPosition(0);
1797     cursor.insertText("*");
1798     int cursorPositionAfter = cursor.position();
1799     cursor.endEditBlock();
1800
1801     QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
1802     QCOMPARE(12, cursorPositionBefore);
1803     QCOMPARE(1, cursorPositionAfter);
1804
1805     doc->undo(&cursor);
1806     QVERIFY(doc->toPlainText() == "AAAABBBBCCCCDDDD");
1807     QCOMPARE(cursor.position(), cursorPositionBefore);
1808     doc->redo(&cursor);
1809     QVERIFY(doc->toPlainText() == "*AAAA*BBBB*CCCC*DDDD");
1810     QCOMPARE(cursor.position(), cursorPositionAfter);
1811 }
1812
1813 void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo2()
1814 {
1815     cursor.insertText("AAAABBBB");
1816     int cursorPositionBefore = cursor.position();
1817     cursor.setPosition(0, QTextCursor::KeepAnchor);
1818     cursor.beginEditBlock();
1819     cursor.removeSelectedText();
1820     cursor.insertText("AAAABBBBCCCCDDDD");
1821     cursor.endEditBlock();
1822     doc->undo(&cursor);
1823     QVERIFY(doc->toPlainText() == "AAAABBBB");
1824     QCOMPARE(cursor.position(), cursorPositionBefore);
1825
1826     cursor.insertText("CCCC");
1827     QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
1828
1829     cursorPositionBefore = cursor.position();
1830     cursor.setPosition(0, QTextCursor::KeepAnchor);
1831     cursor.beginEditBlock();
1832     cursor.removeSelectedText();
1833     cursor.insertText("AAAABBBBCCCCDDDD");
1834     cursor.endEditBlock();
1835
1836     /* this undo now implicitely reinserts two segments, first "CCCCC", then
1837        "AAAABBBB". The test ensures that the two are combined in order to
1838        reconstruct the correct cursor position */
1839     doc->undo(&cursor);
1840
1841
1842     QVERIFY(doc->toPlainText() == "AAAABBBBCCCC");
1843     QCOMPARE(cursor.position(), cursorPositionBefore);
1844 }
1845
1846 void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo3()
1847 {
1848     // verify that it's the position of the beginEditBlock that counts, and not the last edit position
1849     cursor.insertText("AAAABBBB");
1850     int cursorPositionBefore = cursor.position();
1851     cursor.beginEditBlock();
1852     cursor.setPosition(4);
1853     QVERIFY(cursor.position() != cursorPositionBefore);
1854     cursor.insertText("*");
1855     cursor.endEditBlock();
1856     QCOMPARE(cursor.position(), 5);
1857     doc->undo(&cursor);
1858     QCOMPARE(cursor.position(), cursorPositionBefore);
1859 }
1860
1861 QTEST_MAIN(tst_QTextCursor)
1862 #include "tst_qtextcursor.moc"