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
This commit is contained in:
commit
3d2f5f8487
9 changed files with 78 additions and 62 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
for (final Key key : mKeys) {
|
||||
if (key.mCode == code) {
|
||||
mKeyCache.put(keyCode, key);
|
||||
return key;
|
||||
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(code, key);
|
||||
return key;
|
||||
}
|
||||
}
|
||||
mKeyCache.put(code, null);
|
||||
return null;
|
||||
}
|
||||
mKeyCache.put(keyCode, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasKey(Key aKey) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue