aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java8
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java3
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java4
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java21
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java6
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFactory.java20
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java10
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java39
-rw-r--r--java/src/com/android/inputmethod/latin/UserUnigramDictionary.java24
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;