diff options
Diffstat (limited to 'java/src')
9 files changed, 90 insertions, 45 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 0b4fce417..3e45793cb 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -70,6 +70,14 @@ public class Keyboard { public static final int CODE_DASH = '-'; public static final int CODE_SINGLE_QUOTE = '\''; public static final int CODE_DOUBLE_QUOTE = '"'; + // TODO: Check how this should work for right-to-left languages. It seems to stand + // that for rtl languages, a closing parenthesis is a left parenthesis. Is this + // managed by the font? Or is it a different char? + public static final int CODE_CLOSING_PARENTHESIS = ')'; + public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; + public static final int CODE_CLOSING_CURLY_BRACKET = '}'; + public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; + /** Special keys code. These should be aligned with values/keycodes.xml */ public static final int CODE_DUMMY = 0; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 448274ec6..f9593215d 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -152,8 +152,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha boolean voiceButtonOnPrimary) { mSwitchState = SWITCH_STATE_ALPHA; try { - final boolean isSymbols = (mCurrentId != null) ? mCurrentId.isSymbolsKeyboard() : false; - loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, isSymbols); + loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false); } catch (RuntimeException e) { // Get KeyboardId to record which keyboard has been failed to load. final KeyboardId id = getKeyboardId(attribute, false); diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index 7ce92920d..bce787db2 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -91,7 +91,9 @@ class BinaryDictionaryGetter { Log.e(TAG, "Unable to read source data for locale " + locale.toString() + ": falling back to internal dictionary"); } - return Arrays.asList(loadFallbackResource(context, fallbackResId)); + final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId); + if (null == fallbackAsset) return null; + return Arrays.asList(fallbackAsset); } } } diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index 96225f2e9..4baf52e52 100644 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -38,7 +38,6 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; -import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.PopupWindow; @@ -51,7 +50,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; import java.util.List; -public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener { +public class CandidateView extends LinearLayout implements OnClickListener { public interface Listener { public boolean addWordToDictionary(String word); @@ -323,8 +322,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final TextView word = (TextView)inflater.inflate(R.layout.candidate_word, null); word.setTag(i); word.setOnClickListener(this); - if (i == 0) - word.setOnLongClickListener(this); mWords.add(word); mInfos.add((TextView)inflater.inflate(R.layout.candidate_info, null)); mDividers.add(inflater.inflate(R.layout.candidate_divider, null)); @@ -750,22 +747,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } @Override - public boolean onLongClick(View view) { - final Object tag = view.getTag(); - if (!(tag instanceof Integer)) - return true; - final int index = (Integer) tag; - if (index >= mSuggestions.size()) - return true; - - final CharSequence word = mSuggestions.getWord(index); - if (word.length() < 2) - return false; - addToDictionary(word); - return true; - } - - @Override public void onClick(View view) { if (view == mWordToSave) { addToDictionary(((TextView)view).getText()); diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 5e7de3e6b..e987d9f0c 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -32,7 +32,11 @@ public class DictionaryCollection extends Dictionary { } public DictionaryCollection(Dictionary... dictionaries) { - mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries); + if (null == dictionaries) { + mDictionaries = new CopyOnWriteArrayList<Dictionary>(); + } else { + mDictionaries = new CopyOnWriteArrayList<Dictionary>(dictionaries); + } } public DictionaryCollection(Collection<Dictionary> dictionaries) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index bba331868..a35b0f5b0 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -52,13 +52,23 @@ public class DictionaryFactory { } final List<Dictionary> dictList = new LinkedList<Dictionary>(); - for (final AssetFileAddress f : BinaryDictionaryGetter.getDictionaryFiles(locale, - context, fallbackResId)) { - dictList.add(new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null)); + final List<AssetFileAddress> assetFileList = + BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); + if (null != assetFileList) { + for (final AssetFileAddress f : assetFileList) { + dictList.add( + new BinaryDictionary(context, f.mFilename, f.mOffset, f.mLength, null)); + } } - if (null == dictList) return null; - return new DictionaryCollection(dictList); + // null == dictList is not supposed to be possible, but better safe than sorry and it's + // safer for future extension. In this case, rather than returning null, it should be safer + // to return an empty DictionaryCollection. + if (null == dictList) { + return new DictionaryCollection(); + } else { + return new DictionaryCollection(dictList); + } } /** diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index e56aa695d..634dbbdfc 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -33,6 +33,7 @@ public class EditingUtils { * Number of characters we want to look back in order to identify the previous word */ private static final int LOOKBACK_CHARACTER_NUM = 15; + private static final int INVALID_CURSOR_POSITION = -1; private EditingUtils() { // Unintentional empty constructor for singleton. @@ -63,10 +64,11 @@ public class EditingUtils { } private static int getCursorPosition(InputConnection connection) { + if (null == connection) return INVALID_CURSOR_POSITION; ExtractedText extracted = connection.getExtractedText( new ExtractedTextRequest(), 0); if (extracted == null) { - return -1; + return INVALID_CURSOR_POSITION; } return extracted.startOffset + extracted.selectionStart; } @@ -79,6 +81,7 @@ public class EditingUtils { * represents the cursor, then "hello " will be returned. */ public static String getWordAtCursor(InputConnection connection, String separators) { + // getWordRangeAtCursor returns null if the connection is null Range r = getWordRangeAtCursor(connection, separators); return (r == null) ? null : r.mWord; } @@ -88,6 +91,7 @@ public class EditingUtils { * getWordAtCursor. */ public static void deleteWordAtCursor(InputConnection connection, String separators) { + // getWordRangeAtCursor returns null if the connection is null Range range = getWordRangeAtCursor(connection, separators); if (range == null) return; @@ -165,6 +169,7 @@ public class EditingUtils { public static CharSequence getPreviousWord(InputConnection connection, String sentenceSeperators) { //TODO: Should fix this. This could be slow! + if (null == connection) return null; CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); return getPreviousWord(prev, sentenceSeperators); } @@ -194,6 +199,7 @@ public class EditingUtils { } public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) { + if (null == connection) return null; final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); return getThisWord(prev, sentenceSeperators); } @@ -256,12 +262,14 @@ public class EditingUtils { int selStart, int selEnd, String wordSeparators) { if (selStart == selEnd) { // There is just a cursor, so get the word at the cursor + // getWordRangeAtCursor returns null if the connection is null EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators); if (range != null && !TextUtils.isEmpty(range.mWord)) { return new SelectedWord(selStart - range.mCharsBefore, selEnd + range.mCharsAfter, range.mWord); } } else { + if (null == ic) return null; // Is the previous character empty or a word separator? If not, return null. CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); if (!isWordBoundary(charsBefore, wordSeparators)) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index a820a40e3..29cf63de4 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -988,13 +988,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + private static boolean canBeFollowedByPeriod(final int codePoint) { + // TODO: Check again whether there really ain't a better way to check this. + // TODO: This should probably be language-dependant... + return Character.isLetterOrDigit(codePoint) + || codePoint == Keyboard.CODE_SINGLE_QUOTE + || codePoint == Keyboard.CODE_DOUBLE_QUOTE + || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS + || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET + || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET + || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; + } + private void maybeDoubleSpace() { if (mCorrectionMode == Suggest.CORRECTION_NONE) return; final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; - CharSequence lastThree = ic.getTextBeforeCursor(3, 0); + final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 - && Character.isLetterOrDigit(lastThree.charAt(0)) + && canBeFollowedByPeriod(lastThree.charAt(0)) && lastThree.charAt(1) == Keyboard.CODE_SPACE && lastThree.charAt(2) == Keyboard.CODE_SPACE && mHandler.isAcceptingDoubleSpaces()) { @@ -1498,9 +1510,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final WordComposer wordComposer = mWordComposer; // TODO: May need a better way of retrieving previous word - CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), - mSettingsValues.mWordSeparators); - SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( + final InputConnection ic = getCurrentInputConnection(); + final CharSequence prevWord; + if (null == ic) { + prevWord = null; + } else { + prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); + } + // getSuggestedWordBuilder handles gracefully a null value of prevWord + final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( mKeyboardSwitcher.getKeyboardView(), wordComposer, prevWord); boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); @@ -1772,10 +1790,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // We don't want to register as bigrams words separated by a separator. // For example "I will, and you too" : we don't want the pair ("will" "and") to be // a bigram. - CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(), - mSettingsValues.mWordSeparators); - if (!TextUtils.isEmpty(prevWord)) { - mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); + final InputConnection ic = getCurrentInputConnection(); + if (null != ic) { + final CharSequence prevWord = + EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); + if (!TextUtils.isEmpty(prevWord)) { + mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); + } } } } diff --git a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java index 382d64030..e41230b3c 100644 --- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java @@ -36,6 +36,8 @@ import java.util.Set; * for suggesting and re-ordering of candidates. */ public class UserUnigramDictionary extends ExpandableDictionary { + static final boolean ENABLE_USER_UNIGRAM_DICTIONARY = false; + // Weight added to a user picking a new word from the suggestion strip static final int FREQUENCY_FOR_PICKED = 3; // Weight added to a user typing a new word that doesn't get corrected (or is reverted) @@ -71,17 +73,22 @@ public class UserUnigramDictionary extends ExpandableDictionary { private static HashMap<String, String> sDictProjectionMap; static { - sDictProjectionMap = new HashMap<String, String>(); - sDictProjectionMap.put(COLUMN_ID, COLUMN_ID); - sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD); - sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY); - sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); + if (ENABLE_USER_UNIGRAM_DICTIONARY) { + sDictProjectionMap = new HashMap<String, String>(); + sDictProjectionMap.put(COLUMN_ID, COLUMN_ID); + sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD); + sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY); + sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); + } } private static DatabaseHelper sOpenHelper = null; public UserUnigramDictionary(Context context, LatinIME ime, String locale, int dicTypeId) { super(context, dicTypeId); + // Super must be first statement of the constructor... I'd like not to do it if the + // user unigram dictionary is not enabled, but Java won't let me. + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; mIme = ime; mLocale = locale; if (sOpenHelper == null) { @@ -94,22 +101,25 @@ public class UserUnigramDictionary extends ExpandableDictionary { @Override public synchronized boolean isValidWord(CharSequence word) { + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return false; final int frequency = getWordFrequency(word); return frequency >= VALIDITY_THRESHOLD; } @Override public void close() { + super.close(); + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; flushPendingWrites(); // Don't close the database as locale changes will require it to be reopened anyway // Also, the database is written to somewhat frequently, so it needs to be kept alive // throughout the life of the process. // mOpenHelper.close(); - super.close(); } @Override public void loadDictionaryAsync() { + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; // Load the words that correspond to the current input locale Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); try { @@ -134,6 +144,7 @@ public class UserUnigramDictionary extends ExpandableDictionary { @Override public void addWord(String newWord, int addFrequency) { + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; String word = newWord; final int length = word.length(); // Don't add very short or very long words. @@ -156,6 +167,7 @@ public class UserUnigramDictionary extends ExpandableDictionary { * Schedules a background thread to write any pending words to the database. */ public void flushPendingWrites() { + if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; synchronized (mPendingWritesLock) { // Nothing pending? Return if (mPendingWrites.isEmpty()) return; |