1
0
mirror of https://github.com/danog/patches.git synced 2024-12-02 09:17:58 +01:00
patches/qtbase_5_12_8/0007-improve-apostrophe-processing.patch

192 lines
7.0 KiB
Diff
Raw Normal View History

diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index c88497840f..2b08d13834 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -510,14 +510,16 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
const int len = blockIt.length() - 1;
if (relativePos >= len)
return false;
- if (engine->atWordSeparator(relativePos)) {
- ++relativePos;
- while (relativePos < len && engine->atWordSeparator(relativePos))
- ++relativePos;
- } else {
- while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
- ++relativePos;
- }
+ // Patch: Improved apostrophe processing.
+ relativePos = engine->toEdge(relativePos, len, true);
+ // if (engine->atWordSeparator(relativePos)) {
+ // ++relativePos;
+ // while (relativePos < len && engine->atWordSeparator(relativePos))
+ // ++relativePos;
+ // } else {
+ // while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
+ // ++relativePos;
+ // }
newPosition = blockIt.position() + relativePos;
break;
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index a7834587b1..cabe897268 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -3028,7 +3028,8 @@ bool QTextEngine::atWordSeparator(int position) const
case '&':
case '^':
case '*':
- case '\'':
+ // Patch: Make the apostrophe a non-separator for words.
+ //case '\'':
case '"':
case '`':
case '~':
@@ -3041,6 +3042,74 @@ bool QTextEngine::atWordSeparator(int position) const
return false;
}
+// Patch: Improved apostrophe processing.
+// We should consider apostrophes as word separators when there is more than
+// one apostrophe in a row, or when the apostrophe is at the beginning or end
+// of the word.
+int QTextEngine::toEdge(int pos, int len, bool isRightDirection) {
+ const auto step = isRightDirection ? 1 : -1;
+ const auto next = isRightDirection ? 0 : -1;
+
+ QCharAttributes *attributes = const_cast<QCharAttributes *>(this->attributes());
+
+ const auto atApostrophe = [&](int position) {
+ return layoutData->string.at(position).unicode() == '\'';
+ };
+
+ const auto atSepOrApost = [&](int position) {
+ return atApostrophe(position) || atWordSeparator(position);
+ };
+
+ const auto inBounds = [&](int position) {
+ return isRightDirection
+ ? position < len
+ : position > 0;
+ };
+
+ const auto atSepOrSpace = [&](int position) {
+ return attributes[position].whiteSpace || atWordSeparator(position);
+ };
+
+ const auto isApostropheInWord = [&](int position) {
+ if (!atApostrophe(position)) {
+ return false;
+ }
+ auto p = position - 1;
+ if (p <= 0 || atSepOrSpace(p)) {
+ return false;
+ }
+ p = position + 1;
+ if (p >= len || atSepOrSpace(p)) {
+ return false;
+ }
+ return true;
+ };
+
+ auto counter = 0;
+ while (inBounds(pos) && atSepOrApost(pos + next)) {
+ counter++;
+ pos += step;
+ }
+ // If it's not the single apostrophe, then that's non-letter part of text.
+ if (counter > 1 || (counter == 1 && !isApostropheInWord(pos - step + next))) {
+ return pos;
+ }
+
+ bool isPrevApostrophe = false;
+ while (inBounds(pos) && !atSepOrSpace(pos + next)) {
+ bool isNextApostrophe = atApostrophe(pos + next);
+ if (isPrevApostrophe && isNextApostrophe) {
+ break;
+ }
+ pos += step;
+ isPrevApostrophe = isNextApostrophe;
+ }
+ if (isPrevApostrophe) {
+ pos += -step;
+ }
+ return pos;
+}
+
void QTextEngine::setPreeditArea(int position, const QString &preeditText)
{
if (preeditText.isEmpty()) {
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index e9187ea605..51997ba066 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -622,6 +622,8 @@ private:
public:
bool atWordSeparator(int position) const;
+ // Patch: Improved apostrophe processing.
+ int toEdge(int pos, int len, bool isRightDirection);
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0, int from = 0, int count = -1) const;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index f3f0caa379..081c5f03c0 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -706,16 +706,22 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
while (oldPos < len && !attributes[oldPos].graphemeBoundary)
oldPos++;
} else {
- if (oldPos < len && d->atWordSeparator(oldPos)) {
- oldPos++;
- while (oldPos < len && d->atWordSeparator(oldPos))
- oldPos++;
- } else {
- while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
- oldPos++;
- }
+ // Patch: Skip to the end of the current word, not to the start of the next one.
while (oldPos < len && attributes[oldPos].whiteSpace)
oldPos++;
+ // Patch: Improved apostrophe processing.
+ oldPos = d->toEdge(oldPos, len, true);
+ // if (oldPos < len && d->atWordSeparator(oldPos)) {
+ // oldPos++;
+ // while (oldPos < len && d->atWordSeparator(oldPos))
+ // oldPos++;
+ // } else {
+ // while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
+ // oldPos++;
+ // }
+ // Patch: Skip to the end of the current word, not to the start of the next one.
+ //while (oldPos < len && attributes[oldPos].whiteSpace)
+ // oldPos++;
}
return oldPos;
@@ -745,14 +751,16 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
oldPos--;
- if (oldPos && d->atWordSeparator(oldPos-1)) {
- oldPos--;
- while (oldPos && d->atWordSeparator(oldPos-1))
- oldPos--;
- } else {
- while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
- oldPos--;
- }
+ // Patch: Improved apostrophe processing.
+ oldPos = d->toEdge(oldPos, len, false);
+ // if (oldPos && d->atWordSeparator(oldPos-1)) {
+ // oldPos--;
+ // while (oldPos && d->atWordSeparator(oldPos-1))
+ // oldPos--;
+ // } else {
+ // while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
+ // oldPos--;
+ // }
}
return oldPos;