aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSatoshi Kataoka <satok@google.com>2012-07-05 16:53:56 +0900
committerSatoshi Kataoka <satok@google.com>2012-07-05 16:53:56 +0900
commit3d2f5f848764252ecd2f15c2d0d857c1fe7f7eaf (patch)
tree9d3db512a4541c8728545aa474647216d44765cb
parent1930f194c2f3b3a6182906c4378388025dff5686 (diff)
parent0726f466f7789ca112697adf6505870bb821ea17 (diff)
downloadlatinime-3d2f5f848764252ecd2f15c2d0d857c1fe7f7eaf.tar.gz
latinime-3d2f5f848764252ecd2f15c2d0d857c1fe7f7eaf.tar.xz
latinime-3d2f5f848764252ecd2f15c2d0d857c1fe7f7eaf.zip
Merge remote-tracking branch 'goog/master' into mergescript
Conflicts: java/src/com/android/inputmethod/keyboard/Keyboard.java java/src/com/android/inputmethod/latin/LatinIME.java java/src/com/android/inputmethod/latin/Suggest.java Change-Id: I73c1cec1f4bca5139372392e93d55081d814fa6c
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java22
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java31
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java28
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java10
-rw-r--r--native/jni/src/bigram_dictionary.cpp27
-rw-r--r--native/jni/src/bigram_dictionary.h3
-rw-r--r--native/jni/src/binary_format.h7
-rw-r--r--native/jni/src/char_utils.h7
-rw-r--r--native/jni/src/unigram_dictionary.cpp3
9 files changed, 77 insertions, 61 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 6fc630d05..6d85fea27 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -184,19 +184,21 @@ public class Keyboard {
if (code == CODE_UNSPECIFIED) {
return null;
}
- final Integer keyCode = code;
- if (mKeyCache.containsKey(keyCode)) {
- return mKeyCache.get(keyCode);
- }
+ synchronized (mKeyCache) {
+ final int index = mKeyCache.indexOfKey(code);
+ if (index >= 0) {
+ return mKeyCache.valueAt(index);
+ }
- for (final Key key : mKeys) {
- if (key.mCode == code) {
- mKeyCache.put(keyCode, key);
- return key;
+ for (final Key key : mKeys) {
+ if (key.mCode == code) {
+ mKeyCache.put(code, key);
+ return key;
+ }
}
+ mKeyCache.put(code, null);
+ return null;
}
- mKeyCache.put(keyCode, null);
- return null;
}
public boolean hasKey(Key aKey) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6e3540485..5cbf40400 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -208,13 +208,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
switch (msg.what) {
case MSG_UPDATE_SUGGESTIONS:
- latinIme.updateSuggestions();
+ latinIme.updateSuggestionsOrPredictions(false /* isPredictions */);
break;
case MSG_UPDATE_SHIFT_STATE:
switcher.updateShiftState();
break;
case MSG_SET_BIGRAM_PREDICTIONS:
- latinIme.updateBigramPredictions();
+ latinIme.updateSuggestionsOrPredictions(true /* isPredictions */);
break;
}
}
@@ -1006,7 +1006,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// the composing word, reset the last composed word, tell the inputconnection about it.
private void resetEntireInputState() {
resetComposingState(true /* alsoResetLastComposedWord */);
- updateSuggestions();
+ updateSuggestionsOrPredictions(false /* isPredictions */);
mConnection.finishComposingText();
}
@@ -1029,7 +1029,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
separatorCode, prevWord);
}
- updateSuggestions();
+ updateSuggestionsOrPredictions(false /* isPredictions */);
}
public int getCurrentAutoCapsState() {
@@ -1697,7 +1697,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- public void updateSuggestions() {
+ public void updateSuggestionsOrPredictions(final boolean isPredictions) {
+ if (isPredictions) {
+ updateBigramPredictions();
+ } else {
+ updateSuggestions();
+ }
+ }
+
+ private void updateSuggestions() {
+ mHandler.cancelUpdateSuggestions();
+ mHandler.cancelUpdateBigramPredictions();
+
// Check if we have a suggestion engine attached.
if ((mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))) {
if (mWordComposer.isComposingWord()) {
@@ -1711,7 +1722,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.cancelUpdateBigramPredictions();
if (!mWordComposer.isComposingWord()) {
- setPunctuationSuggestions();
+ // We are never called with an empty word composer, but if because of a bug
+ // we are, what we should do here is just call updateBigramsPredictions. This will
+ // update the predictions if the "predict next word" option is on, or display
+ // punctuation signs if it's off.
+ updateBigramPredictions();
return;
}
@@ -1775,7 +1790,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions();
- updateSuggestions();
+ updateSuggestionsOrPredictions(false /* isPredictions */);
}
final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
if (autoCorrection != null) {
@@ -1885,7 +1900,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!showingAddToDictionaryHint) {
// If we're not showing the "Touch again to save", then show corrections again.
// In case the cursor position doesn't change, make sure we show the suggestions again.
- updateBigramPredictions();
+ updateSuggestionsOrPredictions(true /* isPredictions */);
// Updating the predictions right away may be slow and feel unresponsive on slower
// terminals. On the other hand if we just postUpdateBigramPredictions() it will
// take a noticeable delay to update them which may feel uneasy.
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 892245402..5aecc1371 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -272,31 +272,9 @@ public class Suggest implements Dictionary.WordCallback {
mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS);
if (!TextUtils.isEmpty(prevWordForBigram)) {
- getAllBigrams(prevWordForBigram, wordComposer);
- if (TextUtils.isEmpty(consideredWord)) {
- // Nothing entered: return all bigrams for the previous word
- int insertCount = Math.min(mBigramSuggestions.size(), MAX_SUGGESTIONS);
- for (int i = 0; i < insertCount; ++i) {
- addBigramToSuggestions(mBigramSuggestions.get(i));
- }
- } else {
- // Word entered: return only bigrams that match the first char of the typed word
- final char currentChar = consideredWord.charAt(0);
- // TODO: Must pay attention to locale when changing case.
- // TODO: Use codepoint instead of char
- final char currentCharUpper = Character.toUpperCase(currentChar);
- int count = 0;
- final int bigramSuggestionSize = mBigramSuggestions.size();
- for (int i = 0; i < bigramSuggestionSize; i++) {
- final SuggestedWordInfo bigramSuggestion = mBigramSuggestions.get(i);
- final char bigramSuggestionFirstChar =
- (char)bigramSuggestion.codePointAt(0);
- if (bigramSuggestionFirstChar == currentChar
- || bigramSuggestionFirstChar == currentCharUpper) {
- addBigramToSuggestions(bigramSuggestion);
- if (++count > MAX_SUGGESTIONS) break;
- }
- }
+ for (final String key : mDictionaries.keySet()) {
+ final Dictionary dictionary = mDictionaries.get(key);
+ suggestionsSet.addAll(dictionary.getBigrams(wordComposer, prevWordForBigram));
}
}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
index 28847745e..610652ac1 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionaryBigramList.java
@@ -98,11 +98,11 @@ public class UserHistoryDictionaryBigramList {
}
public HashMap<String, Byte> getBigrams(String word1) {
- if (!mBigramMap.containsKey(word1)) {
- return EMPTY_BIGRAM_MAP;
- } else {
- return mBigramMap.get(word1);
- }
+ if (mBigramMap.containsKey(word1)) return mBigramMap.get(word1);
+ // TODO: lower case according to locale
+ final String lowerWord1 = word1.toLowerCase();
+ if (mBigramMap.containsKey(lowerWord1)) return mBigramMap.get(lowerWord1);
+ return EMPTY_BIGRAM_MAP;
}
public boolean removeBigram(String word1, String word2) {
diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp
index 144336981..3bfbfad25 100644
--- a/native/jni/src/bigram_dictionary.cpp
+++ b/native/jni/src/bigram_dictionary.cpp
@@ -105,8 +105,15 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in
// TODO: have "in" arguments before "out" ones, and make out args explicit in the name
const uint8_t* const root = DICT;
- int pos = getBigramListPositionForWord(prevWord, prevWordLength);
+ int pos = getBigramListPositionForWord(prevWord, prevWordLength,
+ false /* forceLowerCaseSearch */);
// getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
+ if (0 == pos) {
+ // If no bigrams for this exact word, search again in lower case.
+ pos = getBigramListPositionForWord(prevWord, prevWordLength,
+ true /* forceLowerCaseSearch */);
+ }
+ // If still no bigrams, we really don't have them!
if (0 == pos) return 0;
int bigramFlags;
int bigramCount = 0;
@@ -141,10 +148,11 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in
// Returns a pointer to the start of the bigram list.
// If the word is not found or has no bigrams, this function returns 0.
int BigramDictionary::getBigramListPositionForWord(const int32_t *prevWord,
- const int prevWordLength) const {
+ const int prevWordLength, const bool forceLowerCaseSearch) const {
if (0 >= prevWordLength) return 0;
const uint8_t* const root = DICT;
- int pos = BinaryFormat::getTerminalPosition(root, prevWord, prevWordLength);
+ int pos = BinaryFormat::getTerminalPosition(root, prevWord, prevWordLength,
+ forceLowerCaseSearch);
if (NOT_VALID_WORD == pos) return 0;
const int flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos);
@@ -164,7 +172,13 @@ void BigramDictionary::fillBigramAddressToFrequencyMapAndFilter(const int32_t *p
const int prevWordLength, std::map<int, int> *map, uint8_t *filter) const {
memset(filter, 0, BIGRAM_FILTER_BYTE_SIZE);
const uint8_t* const root = DICT;
- int pos = getBigramListPositionForWord(prevWord, prevWordLength);
+ int pos = getBigramListPositionForWord(prevWord, prevWordLength,
+ false /* forceLowerCaseSearch */);
+ if (0 == pos) {
+ // If no bigrams for this exact string, search again in lower case.
+ pos = getBigramListPositionForWord(prevWord, prevWordLength,
+ true /* forceLowerCaseSearch */);
+ }
if (0 == pos) return;
int bigramFlags;
@@ -197,10 +211,11 @@ bool BigramDictionary::checkFirstCharacter(unsigned short *word, int *inputCodes
bool BigramDictionary::isValidBigram(const int32_t *word1, int length1, const int32_t *word2,
int length2) const {
const uint8_t* const root = DICT;
- int pos = getBigramListPositionForWord(word1, length1);
+ int pos = getBigramListPositionForWord(word1, length1, false /* forceLowerCaseSearch */);
// getBigramListPositionForWord returns 0 if this word isn't in the dictionary or has no bigrams
if (0 == pos) return false;
- int nextWordPos = BinaryFormat::getTerminalPosition(root, word2, length2);
+ int nextWordPos = BinaryFormat::getTerminalPosition(root, word2, length2,
+ false /* forceLowerCaseSearch */);
if (NOT_VALID_WORD == nextWordPos) return false;
int bigramFlags;
do {
diff --git a/native/jni/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h
index 1ff1b2ec6..5372276cd 100644
--- a/native/jni/src/bigram_dictionary.h
+++ b/native/jni/src/bigram_dictionary.h
@@ -30,7 +30,8 @@ class BigramDictionary {
BigramDictionary(const unsigned char *dict, int maxWordLength);
int getBigrams(const int32_t *word, int length, int *inputCodes, int codesSize,
unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams) const;
- int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength) const;
+ int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength,
+ const bool forceLowerCaseSearch) const;
void fillBigramAddressToFrequencyMapAndFilter(const int32_t *prevWord, const int prevWordLength,
std::map<int, int> *map, uint8_t *filter) const;
bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const;
diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h
index 214ecfa8d..474c854fe 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/binary_format.h
@@ -19,6 +19,7 @@
#include <limits>
#include "bloom_filter.h"
+#include "char_utils.h"
#include "unigram_dictionary.h"
namespace latinime {
@@ -65,7 +66,7 @@ class BinaryFormat {
static int getAttributeAddressAndForwardPointer(const uint8_t* const dict, const uint8_t flags,
int *pos);
static int getTerminalPosition(const uint8_t* const root, const int32_t* const inWord,
- const int length);
+ const int length, const bool forceLowerCaseSearch);
static int getWordAtAddress(const uint8_t* const root, const int address, const int maxDepth,
uint16_t* outWord, int* outUnigramFrequency);
static int computeFrequencyForBigram(const int unigramFreq, const int bigramFreq);
@@ -309,7 +310,7 @@ inline int BinaryFormat::getAttributeAddressAndForwardPointer(const uint8_t* con
// This function gets the byte position of the last chargroup of the exact matching word in the
// dictionary. If no match is found, it returns NOT_VALID_WORD.
inline int BinaryFormat::getTerminalPosition(const uint8_t* const root,
- const int32_t* const inWord, const int length) {
+ const int32_t* const inWord, const int length, const bool forceLowerCaseSearch) {
int pos = 0;
int wordPos = 0;
@@ -318,7 +319,7 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t* const root,
// there was no match (or we would have found it).
if (wordPos > length) return NOT_VALID_WORD;
int charGroupCount = BinaryFormat::getGroupCountAndForwardPointer(root, &pos);
- const int32_t wChar = inWord[wordPos];
+ const int32_t wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos];
while (true) {
// If there are no more character groups in this node, it means we could not
// find a matching character for this depth, therefore there is no match.
diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h
index 607dc5195..21dca9a0a 100644
--- a/native/jni/src/char_utils.h
+++ b/native/jni/src/char_utils.h
@@ -50,8 +50,7 @@ inline static unsigned short toBaseChar(unsigned short c) {
return c;
}
-inline static unsigned short toBaseLowerCase(unsigned short c) {
- c = toBaseChar(c);
+inline static unsigned short toLowerCase(const unsigned short c) {
if (isAsciiUpper(c)) {
return toAsciiLower(c);
} else if (isAscii(c)) {
@@ -60,6 +59,10 @@ inline static unsigned short toBaseLowerCase(unsigned short c) {
return latin_tolower(c);
}
+inline static unsigned short toBaseLowerCase(const unsigned short c) {
+ return toLowerCase(toBaseChar(c));
+}
+
} // namespace latinime
#endif // LATINIME_CHAR_UTILS_H
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 3417d2ba7..22f1657ef 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -817,7 +817,8 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWor
int UnigramDictionary::getFrequency(const int32_t* const inWord, const int length) const {
const uint8_t* const root = DICT_ROOT;
- int pos = BinaryFormat::getTerminalPosition(root, inWord, length);
+ int pos = BinaryFormat::getTerminalPosition(root, inWord, length,
+ false /* forceLowerCaseSearch */);
if (NOT_VALID_WORD == pos) {
return NOT_A_PROBABILITY;
}