From cfed2739221105163893cecdc9402cd9ddc0ab93 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 15 Sep 2011 14:31:24 +0900 Subject: [PATCH] Add an option to user dict to match more precise locales This should not be used lightly, as it violates the general contract of locale, and does kill some legitimate (albeit alledgedly rare) use patterns. Currently, the spell checker uses this because it uses a negative logic: it should match broadly, and when in doubt, match even more broadly, which is almost never the case of something that uses the locale. In other words: don't use this option unless you are very, VERY sure that's what you want. Hint: it isn't Bug: 5280929 Change-Id: Ib3cae319c692161d653630038c5bcde1f4340c05 --- .../SynchronouslyLoadedUserDictionary.java | 7 +++- .../inputmethod/latin/UserDictionary.java | 38 +++++++++++++++++-- .../AndroidSpellCheckerService.java | 2 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java index 4a812b3a9..b526fe510 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java @@ -23,7 +23,12 @@ import com.android.inputmethod.keyboard.ProximityInfo; public class SynchronouslyLoadedUserDictionary extends UserDictionary { public SynchronouslyLoadedUserDictionary(final Context context, final String locale) { - super(context, locale); + this(context, locale, false); + } + + public SynchronouslyLoadedUserDictionary(final Context context, final String locale, + final boolean alsoUseMoreRestrictiveLocales) { + super(context, locale, alsoUseMoreRestrictiveLocales); } @Override diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index d696a6158..67da4fa50 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -29,6 +29,8 @@ import android.text.TextUtils; import com.android.inputmethod.keyboard.ProximityInfo; +import java.util.Arrays; + public class UserDictionary extends ExpandableDictionary { private static final String[] PROJECTION_QUERY = { @@ -44,11 +46,18 @@ public class UserDictionary extends ExpandableDictionary { private ContentObserver mObserver; final private String mLocale; + final private boolean mAlsoUseMoreRestrictiveLocales; - public UserDictionary(Context context, String locale) { + public UserDictionary(final Context context, final String locale) { + this(context, locale, false); + } + + public UserDictionary(final Context context, final String locale, + final boolean alsoUseMoreRestrictiveLocales) { super(context, Suggest.DIC_USER); if (null == locale) throw new NullPointerException(); // Catch the error earlier mLocale = locale; + mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales; // Perform a managed query. The Activity will handle closing and re-querying the cursor // when needed. ContentResolver cres = context.getContentResolver(); @@ -81,12 +90,13 @@ public class UserDictionary extends ExpandableDictionary { // For this example, we'll look at the "en_US_POSIX" case. final String[] localeElements = TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3); + final int length = localeElements.length; 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) { + for (int i = 0; i < length; ++i) { // i | localeSoFar | localeElements // 0 | "" | ["en", "US", "POSIX"] // 1 | "en_" | ["en", "US", "POSIX"] @@ -101,9 +111,29 @@ public class UserDictionary extends ExpandableDictionary { } // 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() + + final String[] requestArguments; + // If length == 3, we already have all the arguments we need (common prefix is meaningless + // inside variants + if (mAlsoUseMoreRestrictiveLocales && length < 3) { + request.append(" or (locale like ?)"); + // The following creates an array with one more (null) position + final String[] localeElementsWithMoreRestrictiveLocalesIncluded = + Arrays.copyOf(localeElements, length + 1); + localeElementsWithMoreRestrictiveLocalesIncluded[length] = + localeElements[length - 1] + "_%"; + requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded; + // If for example localeElements = ["en"] + // then requestArguments = ["en", "en_%"] + // and request = (locale is NULL) or (locale=?) or (locale like ?) + // If localeElements = ["en", "en_US"] + // then requestArguments = ["en", "en_US", "en_US_%"] + } else { + requestArguments = localeElements; + } + final Cursor cursor = getContext().getContentResolver() .query(Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), - localeElements, null); + requestArguments, 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 dfa0abf1b..0864526d9 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -237,7 +237,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final String localeStr = locale.toString(); Dictionary userDict = mUserDictionaries.get(localeStr); if (null == userDict) { - userDict = new SynchronouslyLoadedUserDictionary(this, localeStr); + userDict = new SynchronouslyLoadedUserDictionary(this, localeStr, true); mUserDictionaries.put(localeStr, userDict); } dictionaryCollection.addDictionary(userDict);