From 330f6e359897f77cf50f67141d09e94c371121ff Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Fri, 4 Apr 2014 07:31:24 +0300 Subject: QTextLayout: Fix cursor movement from invalid position Actually guarantee cursor doesn't move in this case for both logical and visual modes (just what the documentation says we already do ;) Change-Id: Iabdca7aa1d205672386a0095e3487e585611cdb5 Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 15 ++++++---- src/gui/text/qtextlayout.cpp | 5 +++- tests/auto/other/qcomplextext/tst_qcomplextext.cpp | 33 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 53fd37abba..35950c709b 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -3138,11 +3138,12 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end, int QTextEngine::previousLogicalPosition(int oldPos) const { const QCharAttributes *attrs = attributes(); - if (!attrs || oldPos < 0) + int len = block.isValid() ? block.length() - 1 + : layoutData->string.length(); + Q_ASSERT(len <= layoutData->string.length()); + if (!attrs || oldPos <= 0 || oldPos > len) return oldPos; - if (oldPos <= 0) - return 0; oldPos--; while (oldPos && !attrs[oldPos].graphemeBoundary) oldPos--; @@ -3224,8 +3225,7 @@ int QTextEngine::beginningOfLine(int lineNum) int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation op) { - if (!layoutData) - itemize(); + itemize(); bool moveRight = (op == QTextCursor::Right); bool alignRight = isRightToLeft(); @@ -3233,7 +3233,8 @@ int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation return moveRight ^ alignRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos); int lineNum = lineNumberForTextPosition(pos); - Q_ASSERT(lineNum >= 0); + if (lineNum < 0) + return pos; QVector insertionPoints; insertionPointsForLine(lineNum, insertionPoints); @@ -3256,6 +3257,8 @@ int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation if (lineNum > 0) return alignRight ? beginningOfLine(lineNum - 1) : endOfLine(lineNum - 1); } + + break; } return pos; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 0c9866c6cf..c3cf2e56bb 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -674,7 +674,10 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const { const QCharAttributes *attributes = d->attributes(); - if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length()) + int len = d->block.isValid() ? d->block.length() - 1 + : d->layoutData->string.length(); + Q_ASSERT(len <= d->layoutData->string.length()); + if (!attributes || oldPos <= 0 || oldPos > len) return oldPos; if (mode == SkipCharacters) { diff --git a/tests/auto/other/qcomplextext/tst_qcomplextext.cpp b/tests/auto/other/qcomplextext/tst_qcomplextext.cpp index 7eb8479372..cc444872ec 100644 --- a/tests/auto/other/qcomplextext/tst_qcomplextext.cpp +++ b/tests/auto/other/qcomplextext/tst_qcomplextext.cpp @@ -71,6 +71,8 @@ private slots: void bidiCursorMovement(); void bidiCursorLogicalMovement_data(); void bidiCursorLogicalMovement(); + void bidiInvalidCursorNoMovement_data(); + void bidiInvalidCursorNoMovement(); }; tst_QComplexText::tst_QComplexText() @@ -272,6 +274,37 @@ void tst_QComplexText::bidiCursorLogicalMovement() } while (moved); } +void tst_QComplexText::bidiInvalidCursorNoMovement_data() +{ + bidiCursorMovement_data(); +} + +void tst_QComplexText::bidiInvalidCursorNoMovement() +{ + QFETCH(QString, logical); + QFETCH(int, basicDir); + + QTextLayout layout(logical); + + QTextOption option = layout.textOption(); + option.setTextDirection(basicDir == QChar::DirL ? Qt::LeftToRight : Qt::RightToLeft); + layout.setTextOption(option); + + // visual + QCOMPARE(layout.rightCursorPosition(-1000), -1000); + QCOMPARE(layout.rightCursorPosition(1000), 1000); + + QCOMPARE(layout.leftCursorPosition(-1000), -1000); + QCOMPARE(layout.leftCursorPosition(1000), 1000); + + // logical + QCOMPARE(layout.nextCursorPosition(-1000), -1000); + QCOMPARE(layout.nextCursorPosition(1000), 1000); + + QCOMPARE(layout.previousCursorPosition(-1000), -1000); + QCOMPARE(layout.previousCursorPosition(1000), 1000); +} + void tst_QComplexText::bidiCursor_PDF() { QString str = QString::fromUtf8("\342\200\252hello\342\200\254"); -- cgit v1.2.3