diff options
Diffstat (limited to 'java/src')
-rw-r--r-- | java/src/com/android/inputmethod/latin/UserDictionary.java | 38 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java | 38 |
2 files changed, 70 insertions, 6 deletions
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index 6608d8268..d696a6158 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -25,16 +25,17 @@ import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.provider.UserDictionary.Words; +import android.text.TextUtils; import com.android.inputmethod.keyboard.ProximityInfo; public class UserDictionary extends ExpandableDictionary { - + private static final String[] PROJECTION_QUERY = { Words.WORD, Words.FREQUENCY, }; - + private static final String[] PROJECTION_ADD = { Words._ID, Words.FREQUENCY, @@ -42,10 +43,11 @@ public class UserDictionary extends ExpandableDictionary { }; private ContentObserver mObserver; - private String mLocale; + final private String mLocale; public UserDictionary(Context context, String locale) { super(context, Suggest.DIC_USER); + if (null == locale) throw new NullPointerException(); // Catch the error earlier mLocale = locale; // Perform a managed query. The Activity will handle closing and re-querying the cursor // when needed. @@ -73,9 +75,35 @@ public class UserDictionary extends ExpandableDictionary { @Override public void loadDictionaryAsync() { + // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"], + // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3. + // This is correct for locale processing. + // For this example, we'll look at the "en_US_POSIX" case. + final String[] localeElements = + TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3); + + final StringBuilder request = new StringBuilder("(locale is NULL)"); + String localeSoFar = ""; + // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ; + // and request = "(locale is NULL)" + for (int i = 0; i < localeElements.length; ++i) { + // i | localeSoFar | localeElements + // 0 | "" | ["en", "US", "POSIX"] + // 1 | "en_" | ["en", "US", "POSIX"] + // 2 | "en_US_" | ["en", "en_US", "POSIX"] + localeElements[i] = localeSoFar + localeElements[i]; + localeSoFar = localeElements[i] + "_"; + // i | request + // 0 | "(locale is NULL)" + // 1 | "(locale is NULL) or (locale=?)" + // 2 | "(locale is NULL) or (locale=?) or (locale=?)" + request.append(" or (locale=?)"); + } + // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_" + // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)" Cursor cursor = getContext().getContentResolver() - .query(Words.CONTENT_URI, PROJECTION_QUERY, "(locale IS NULL) or (locale=?)", - new String[] { mLocale }, null); + .query(Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), + localeElements, null); addWords(cursor); } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 3cf8788aa..dfa0abf1b 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -282,6 +282,42 @@ public class AndroidSpellCheckerService extends SpellCheckerService { mLocale = LocaleUtils.constructLocaleFromString(localeString); } + /** + * Finds out whether a particular string should be filtered out of spell checking. + * + * This will loosely match URLs, numbers, symbols. + * + * @param text the string to evaluate. + * @return true if we should filter this text out, false otherwise + */ + private boolean shouldFilterOut(final String text) { + if (TextUtils.isEmpty(text) || text.length() <= 1) return true; + + // TODO: check if an equivalent processing can't be done more quickly with a + // compiled regexp. + // Filter by first letter + final int firstCodePoint = text.codePointAt(0); + // Filter out words that don't start with a letter or an apostrophe + if (!Character.isLetter(firstCodePoint) + && '\'' != firstCodePoint) return true; + + // Filter contents + final int length = text.length(); + int letterCount = 0; + for (int i = 0; i < length; ++i) { + final int codePoint = text.codePointAt(i); + // Any word containing a '@' is probably an e-mail address + // Any word containing a '/' is probably either an ad-hoc combination of two + // words or a URI - in either case we don't want to spell check that + if ('@' == codePoint + || '/' == codePoint) return true; + if (Character.isLetter(codePoint)) ++letterCount; + } + // Guestimate heuristic: perform spell checking if at least 3/4 of the characters + // in this word are letters + return (letterCount * 4 < length * 3); + } + // Note : this must be reentrant /** * Gets a list of suggestions for a specific string. This returns a list of possible @@ -293,7 +329,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final int suggestionsLimit) { final String text = textInfo.getText(); - if (TextUtils.isEmpty(text)) return EMPTY_SUGGESTIONS_INFO; + if (shouldFilterOut(text)) return EMPTY_SUGGESTIONS_INFO; final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(suggestionsLimit); |