diff options
| -rw-r--r-- | core/java/android/text/method/WordIterator.java | 37 | ||||
| -rw-r--r-- | core/java/android/widget/SpellChecker.java | 17 |
2 files changed, 39 insertions, 15 deletions
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java index 17938a8cf7f3..33e96a8638da 100644 --- a/core/java/android/text/method/WordIterator.java +++ b/core/java/android/text/method/WordIterator.java @@ -17,6 +17,8 @@ package android.text.method; import android.annotation.NonNull; +import android.icu.lang.UCharacter; +import android.icu.lang.UProperty; import android.icu.text.BreakIterator; import android.text.CharSequenceCharacterIterator; import android.text.Selection; @@ -321,6 +323,27 @@ public class WordIterator implements Selection.PositionIterator { return false; } + /** + * Indicates if the codepoint is a mid-word-only punctuation. + * + * At the moment, this is locale-independent, and includes all the characters in + * the MidLetter, MidNumLet, and Single_Quote class of Unicode word breaking algorithm (see + * UAX #29 "Unicode Text Segmentation" at http://unicode.org/reports/tr29/). These are all the + * characters that according to the rules WB6 and WB7 of UAX #29 prevent word breaks if they are + * in the middle of a word, but they become word breaks if they happen at the end of a word + * (accroding to rule WB999 that breaks word in any place that is not prohibited otherwise). + * + * @param locale the locale to consider the codepoint in. Presently ignored. + * @param codePoint the codepoint to check. + * @return True if the codepoint is a mid-word punctuation. + */ + public static boolean isMidWordPunctuation(Locale locale, int codePoint) { + final int wb = UCharacter.getIntPropertyValue(codePoint, UProperty.WORD_BREAK); + return (wb == UCharacter.WordBreak.MIDLETTER + || wb == UCharacter.WordBreak.MIDNUMLET + || wb == UCharacter.WordBreak.SINGLE_QUOTE); + } + private boolean isPunctuationStartBoundary(int offset) { return isOnPunctuation(offset) && !isAfterPunctuation(offset); } @@ -331,13 +354,13 @@ public class WordIterator implements Selection.PositionIterator { private static boolean isPunctuation(int cp) { final int type = Character.getType(cp); - return (type == Character.CONNECTOR_PUNCTUATION || - type == Character.DASH_PUNCTUATION || - type == Character.END_PUNCTUATION || - type == Character.FINAL_QUOTE_PUNCTUATION || - type == Character.INITIAL_QUOTE_PUNCTUATION || - type == Character.OTHER_PUNCTUATION || - type == Character.START_PUNCTUATION); + return (type == Character.CONNECTOR_PUNCTUATION + || type == Character.DASH_PUNCTUATION + || type == Character.END_PUNCTUATION + || type == Character.FINAL_QUOTE_PUNCTUATION + || type == Character.INITIAL_QUOTE_PUNCTUATION + || type == Character.OTHER_PUNCTUATION + || type == Character.START_PUNCTUATION); } private boolean isAfterLetterOrDigit(int offset) { diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index e7031fe51061..3d4f54624ecf 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -277,18 +277,19 @@ public class SpellChecker implements SpellCheckerSessionListener { // Do not check this word if the user is currently editing it final boolean isEditing; - // Defer spell check when typing a word with an interior apostrophe. - // TODO: a better solution to this would be to make the word - // iterator locale-sensitive and include the apostrophe in - // languages that use it (such as English). - final boolean apostrophe = (selectionStart == end + 1 && editable.charAt(end) == '\''); - if (mIsSentenceSpellCheckSupported) { + // Defer spell check when typing a word ending with a punctuation like an apostrophe + // which could end up being a mid-word punctuation. + if (selectionStart == end + 1 + && WordIterator.isMidWordPunctuation( + mCurrentLocale, Character.codePointBefore(editable, end + 1))) { + isEditing = false; + } else if (mIsSentenceSpellCheckSupported) { // Allow the overlap of the cursor and the first boundary of the spell check span // no to skip the spell check of the following word because the // following word will never be spell-checked even if the user finishes composing - isEditing = !apostrophe && (selectionEnd <= start || selectionStart > end); + isEditing = selectionEnd <= start || selectionStart > end; } else { - isEditing = !apostrophe && (selectionEnd < start || selectionStart > end); + isEditing = selectionEnd < start || selectionStart > end; } if (start >= 0 && end > start && isEditing) { spellCheckSpan.setSpellCheckInProgress(true); |