aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java37
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java75
3 files changed, 79 insertions, 39 deletions
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index 164d2b748..161ef09b8 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -51,7 +51,7 @@ public class SuggestionSpanUtils {
public static final Field FIELD_FLAG_AUTO_CORRECTION
= CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION");
public static final Field FIELD_SUGGESTION_MAX_SIZE
- = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTION_MAX_SIZE");
+ = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE");
public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils
.getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);;
public static final Integer OBJ_SUGGESTION_MAX_SIZE = (Integer) CompatUtils
@@ -63,7 +63,7 @@ public class SuggestionSpanUtils {
if (LatinImeLogger.sDBG) {
if (SUGGESTION_SPAN_IS_SUPPORTED
&& (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null)) {
- Log.e(TAG, "Field is accidentially null.");
+ throw new RuntimeException("Field is accidentially null.");
}
}
}
@@ -71,7 +71,7 @@ public class SuggestionSpanUtils {
public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
Context context, CharSequence text) {
if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null
- || OBJ_FLAG_AUTO_CORRECTION == null) {
+ || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null) {
return text;
}
final Spannable spannable = text instanceof Spannable
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index bf1e22095..65f8a79df 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -69,6 +69,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private Resources mResources;
private KeyboardState mState;
+ private static final int UNSHIFT = 0;
+ private static final int MANUAL_SHIFT = 1;
+ private static final int AUTOMATIC_SHIFT = 2;
private KeyboardId mMainKeyboardId;
private KeyboardId mSymbolsKeyboardId;
@@ -391,7 +394,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return false;
}
- public boolean isAutomaticTemporaryUpperCase() {
+ private boolean isAutomaticTemporaryUpperCase() {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null)
return latinKeyboard.isAutomaticTemporaryUpperCase();
@@ -412,13 +415,19 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
return false;
}
- private void setManualTemporaryUpperCase(boolean shifted) {
+ private void setShift(int shiftMode) {
LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null) {
+ if (latinKeyboard == null)
+ return;
+ if (shiftMode == AUTOMATIC_SHIFT) {
+ latinKeyboard.setAutomaticTemporaryUpperCase();
+ mKeyboardView.invalidateAllKeys();
+ } else {
+ final boolean shifted = (shiftMode == MANUAL_SHIFT);
// On non-distinct multi touch panel device, we should also turn off the shift locked
// state when shift key is pressed to go to normal mode.
- // On the other hand, on distinct multi touch panel device, turning off the shift locked
- // state with shift key pressing is handled by onReleaseShift().
+ // On the other hand, on distinct multi touch panel device, turning off the shift
+ // locked state with shift key pressing is handled by onReleaseShift().
if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) {
latinKeyboard.setShiftLocked(false);
}
@@ -428,14 +437,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
}
- private void setAutomaticTemporaryUpperCase() {
- LatinKeyboard latinKeyboard = getLatinKeyboard();
- if (latinKeyboard != null) {
- latinKeyboard.setAutomaticTemporaryUpperCase();
- mKeyboardView.invalidateAllKeys();
- }
- }
-
private void setShiftLocked(boolean shiftLocked) {
LatinKeyboard latinKeyboard = getLatinKeyboard();
if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) {
@@ -454,7 +455,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
+ " state=" + mState);
}
if (isAlphabetMode()) {
- setManualTemporaryUpperCase(!isShiftedOrShiftLocked());
+ setShift(isShiftedOrShiftLocked() ? UNSHIFT : MANUAL_SHIFT);
} else {
toggleShiftInSymbol();
}
@@ -516,9 +517,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (!isShiftLocked && !mState.isShiftKeyIgnoring()) {
if (mState.isShiftKeyReleasing() && mInputMethodService.getCurrentAutoCapsState()) {
// Only when shift key is releasing, automatic temporary upper case will be set.
- setAutomaticTemporaryUpperCase();
+ setShift(AUTOMATIC_SHIFT);
} else {
- setManualTemporaryUpperCase(mState.isShiftKeyMomentary());
+ setShift(mState.isShiftKeyMomentary() ? MANUAL_SHIFT : UNSHIFT);
}
}
}
@@ -541,11 +542,11 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (isShiftLocked) {
// Shift key is pressed while caps lock state, we will treat this state as shifted
// caps lock state and mark as if shift key pressed while normal state.
- setManualTemporaryUpperCase(true);
+ setShift(MANUAL_SHIFT);
} else if (isAutomaticTemporaryUpperCase) {
// Shift key is pressed while automatic temporary upper case, we have to move to
// manual temporary upper case.
- setManualTemporaryUpperCase(true);
+ setShift(MANUAL_SHIFT);
} else if (isShiftedOrShiftLocked) {
// In manual upper case state, we just record shift key has been pressing while
// shifted state.
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 9dfbe7a54..a89ef001e 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -415,10 +415,31 @@ public class AndroidSpellCheckerService extends SpellCheckerService
}
private static class AndroidSpellCheckerSession extends Session {
+ private static final int SCRIPT_LATIN = 0;
+ private static final int SCRIPT_CYRILLIC = 1;
+ private static final TreeMap<String, Integer> mLanguageToScript;
+ static {
+ // List of the supported languages and their associated script. We won't check
+ // words written in another script than the selected script, because we know we
+ // don't have those in our dictionary so we will underline everything and we
+ // will never have any suggestions, so it makes no sense checking them.
+ mLanguageToScript = new TreeMap<String, Integer>();
+ mLanguageToScript.put("en", SCRIPT_LATIN);
+ mLanguageToScript.put("fr", SCRIPT_LATIN);
+ mLanguageToScript.put("de", SCRIPT_LATIN);
+ mLanguageToScript.put("nl", SCRIPT_LATIN);
+ mLanguageToScript.put("cs", SCRIPT_LATIN);
+ mLanguageToScript.put("es", SCRIPT_LATIN);
+ mLanguageToScript.put("it", SCRIPT_LATIN);
+ mLanguageToScript.put("ru", SCRIPT_CYRILLIC);
+ }
+
// Immutable, but need the locale which is not available in the constructor yet
private DictionaryPool mDictionaryPool;
// Likewise
private Locale mLocale;
+ // Cache this for performance
+ private int mScript; // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now.
private final AndroidSpellCheckerService mService;
@@ -431,38 +452,56 @@ public class AndroidSpellCheckerService extends SpellCheckerService
final String localeString = getLocale();
mDictionaryPool = mService.getDictionaryPool(localeString);
mLocale = LocaleUtils.constructLocaleFromString(localeString);
+ final Integer script = mLanguageToScript.get(mLocale.getLanguage());
+ if (null == script) {
+ throw new RuntimeException("We have been called with an unsupported language: \""
+ + mLocale.getLanguage() + "\". Framework bug?");
+ }
+ mScript = script;
}
/*
* Returns whether the code point is a letter that makes sense for the specified
* locale for this spell checker.
* The dictionaries supported by Latin IME are described in res/xml/spellchecker.xml
- * and is limited to EFIGS language.
- * Hence at the moment this explicitly excludes non-Latin scripts, including CJK
- * characters, but also Cyrillic, Arabic or Hebrew characters.
- * The locale should be used to rule out inappropriate characters when we support
- * spellchecking other languages like Russian.
+ * and is limited to EFIGS languages and Russian.
+ * Hence at the moment this explicitly tests for Cyrillic characters or Latin characters
+ * as appropriate, and explicitly excludes CJK, Arabic and Hebrew characters.
*/
private static boolean isLetterCheckableByLanguage(final int codePoint,
- final Locale locale) {
- // Our supported dictionaries (EFIGS) at the moment only includes characters
- // in the C0, C1, Latin Extended A and B, IPA extensions unicode blocks.
- // As it happens, those are back-to-back in the code range 0x40 to 0x2AF, so
- // the below is a very efficient way to test for it. As for the 0-0x3F, it's
- // excluded from isLetter anyway.
- // TODO: change this to use locale when we support other scripts
- return codePoint <= 0x2AF && Character.isLetter(codePoint);
+ final int script) {
+ switch (script) {
+ case SCRIPT_LATIN:
+ // Our supported latin script dictionaries (EFIGS) at the moment only include
+ // characters in the C0, C1, Latin Extended A and B, IPA extensions unicode
+ // blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF,
+ // so the below is a very efficient way to test for it. As for the 0-0x3F, it's
+ // excluded from isLetter anyway.
+ return codePoint <= 0x2AF && Character.isLetter(codePoint);
+ case SCRIPT_CYRILLIC:
+ // All Cyrillic characters are in the 400~52F block. There are some in the upper
+ // Unicode range, but they are archaic characters that are not used in modern
+ // russian and are not used by our dictionary.
+ return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint);
+ default:
+ // Should never come here
+ throw new RuntimeException("Impossible value of script: " + script);
+ }
}
/**
* Finds out whether a particular string should be filtered out of spell checking.
*
- * This will loosely match URLs, numbers, symbols.
+ * This will loosely match URLs, numbers, symbols. To avoid always underlining words that
+ * we know we will never recognize, this accepts a script identifier that should be one
+ * of the SCRIPT_* constants defined above, to rule out quickly characters from very
+ * different languages.
*
* @param text the string to evaluate.
+ * @param script the identifier for the script this spell checker recognizes
* @return true if we should filter this text out, false otherwise
*/
- private static boolean shouldFilterOut(final String text, final Locale locale) {
+ private static boolean shouldFilterOut(final String text, final int script) {
if (TextUtils.isEmpty(text) || text.length() <= 1) return true;
// TODO: check if an equivalent processing can't be done more quickly with a
@@ -470,7 +509,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
// Filter by first letter
final int firstCodePoint = text.codePointAt(0);
// Filter out words that don't start with a letter or an apostrophe
- if (!isLetterCheckableByLanguage(firstCodePoint, locale)
+ if (!isLetterCheckableByLanguage(firstCodePoint, script)
&& '\'' != firstCodePoint) return true;
// Filter contents
@@ -483,7 +522,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
// words or a URI - in either case we don't want to spell check that
if ('@' == codePoint
|| '/' == codePoint) return true;
- if (isLetterCheckableByLanguage(codePoint, locale)) ++letterCount;
+ if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
}
// Guestimate heuristic: perform spell checking if at least 3/4 of the characters
// in this word are letters
@@ -502,7 +541,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
try {
final String text = textInfo.getText();
- if (shouldFilterOut(text, mLocale)) {
+ if (shouldFilterOut(text, mScript)) {
DictAndProximity dictInfo = null;
try {
dictInfo = mDictionaryPool.takeOrGetNull();