summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/widget/Editor.java4
-rw-r--r--core/java/android/widget/SpellChecker.java35
-rw-r--r--core/java/android/widget/TextView.java31
3 files changed, 62 insertions, 8 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 91c989dd8615..50d28abc25ad 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -499,6 +499,10 @@ public class Editor {
* Create new SpellCheckSpans on the modified region.
*/
private void updateSpellCheckSpans(int start, int end, boolean createSpellChecker) {
+ // Remove spans whose adjacent characters are text not punctuation
+ mTextView.removeAdjacentSuggestionSpans(start);
+ mTextView.removeAdjacentSuggestionSpans(end);
+
if (mTextView.isTextEditable() && mTextView.isSuggestionsEnabled() &&
!(mTextView instanceof ExtractEditText)) {
if (mSpellChecker == null && createSpellChecker) {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 9e7f97ea16eb..b204dfd0c032 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -753,4 +753,39 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
}
}
+
+ public static boolean haveWordBoundariesChanged(final Editable editable, final int start,
+ final int end, final int spanStart, final int spanEnd) {
+ final boolean haveWordBoundariesChanged;
+ if (spanEnd != start && spanStart != end) {
+ haveWordBoundariesChanged = true;
+ if (DBG) {
+ Log.d(TAG, "(1) Text inside the span has been modified. Remove.");
+ }
+ } else if (spanEnd == start && start < editable.length()) {
+ final int codePoint = Character.codePointAt(editable, start);
+ haveWordBoundariesChanged = Character.isLetterOrDigit(codePoint);
+ if (DBG) {
+ Log.d(TAG, "(2) Characters have been appended to the spanned text. "
+ + (haveWordBoundariesChanged ? "Remove.<" : "Keep. <") + (char)(codePoint)
+ + ">, " + editable + ", " + editable.subSequence(spanStart, spanEnd) + ", "
+ + start);
+ }
+ } else if (spanStart == end && end > 0) {
+ final int codePoint = Character.codePointBefore(editable, end);
+ haveWordBoundariesChanged = Character.isLetterOrDigit(codePoint);
+ if (DBG) {
+ Log.d(TAG, "(3) Characters have been prepended to the spanned text. "
+ + (haveWordBoundariesChanged ? "Remove.<" : "Keep.<") + (char)(codePoint)
+ + ">, " + editable + ", " + editable.subSequence(spanStart, spanEnd) + ", "
+ + end);
+ }
+ } else {
+ if (DBG) {
+ Log.d(TAG, "(4) Characters adjacent to the spanned text were deleted. Keep.");
+ }
+ haveWordBoundariesChanged = false;
+ }
+ return haveWordBoundariesChanged;
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 71baa9004680..816bb18dcd56 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7362,27 +7362,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
// The spans that are inside or intersect the modified region no longer make sense
- removeIntersectingSpans(start, start + before, SpellCheckSpan.class);
- removeIntersectingSpans(start, start + before, SuggestionSpan.class);
+ removeIntersectingNonAdjacentSpans(start, start + before, SpellCheckSpan.class);
+ removeIntersectingNonAdjacentSpans(start, start + before, SuggestionSpan.class);
}
// Removes all spans that are inside or actually overlap the start..end range
- private <T> void removeIntersectingSpans(int start, int end, Class<T> type) {
+ private <T> void removeIntersectingNonAdjacentSpans(int start, int end, Class<T> type) {
if (!(mText instanceof Editable)) return;
Editable text = (Editable) mText;
T[] spans = text.getSpans(start, end, type);
final int length = spans.length;
for (int i = 0; i < length; i++) {
- final int s = text.getSpanStart(spans[i]);
- final int e = text.getSpanEnd(spans[i]);
- // Spans that are adjacent to the edited region will be handled in
- // updateSpellCheckSpans. Result depends on what will be added (space or text)
- if (e == start || s == end) break;
+ final int spanStart = text.getSpanStart(spans[i]);
+ final int spanEnd = text.getSpanEnd(spans[i]);
+ if (spanEnd == start || spanStart == end) break;
text.removeSpan(spans[i]);
}
}
+ void removeAdjacentSuggestionSpans(final int pos) {
+ if (!(mText instanceof Editable)) return;
+ final Editable text = (Editable) mText;
+
+ final SuggestionSpan[] spans = text.getSpans(pos, pos, SuggestionSpan.class);
+ final int length = spans.length;
+ for (int i = 0; i < length; i++) {
+ final int spanStart = text.getSpanStart(spans[i]);
+ final int spanEnd = text.getSpanEnd(spans[i]);
+ if (spanEnd == pos || spanStart == pos) {
+ if (SpellChecker.haveWordBoundariesChanged(text, pos, pos, spanStart, spanEnd)) {
+ text.removeSpan(spans[i]);
+ }
+ }
+ }
+ }
+
/**
* Not private so it can be called from an inner class without going
* through a thunk.