aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java3
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java6
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java40
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java100
4 files changed, 136 insertions, 13 deletions
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
index 7d673175e..93106ac27 100644
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtils.java
@@ -38,8 +38,7 @@ public class EditingUtils {
private static int getCursorPosition(InputConnection connection) {
if (null == connection) return INVALID_CURSOR_POSITION;
- ExtractedText extracted = connection.getExtractedText(
- new ExtractedTextRequest(), 0);
+ final ExtractedText extracted = connection.getExtractedText(new ExtractedTextRequest(), 0);
if (extracted == null) {
return INVALID_CURSOR_POSITION;
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e8211aecf..fd8f7827f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -635,6 +635,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Log.d(TAG, "onStartInputView: editorInfo:"
+ String.format("inputType=0x%08x imeOptions=0x%08x",
editorInfo.inputType, editorInfo.imeOptions));
+ Log.d(TAG, "All caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0)
+ + ", sentence caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0)
+ + ", word caps = "
+ + ((editorInfo.inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0));
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, mPrefs);
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index d82d503c4..3c818cc56 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -174,6 +174,7 @@ public class BinaryDictInputOutput {
private static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767
private static final int MAX_TERMINAL_FREQUENCY = 255;
+ private static final int MAX_BIGRAM_FREQUENCY = 15;
// Arbitrary limit to how much passes we consider address size compression should
// terminate in. At the time of this writing, our largest dictionary completes
@@ -722,15 +723,17 @@ public class BinaryDictInputOutput {
}
/**
- * Makes the flag value for an attribute.
+ * Makes the flag value for a bigram.
*
- * @param more whether there are more attributes after this one.
- * @param offset the offset of the attribute.
- * @param frequency the frequency of the attribute, 0..15
+ * @param more whether there are more bigrams after this one.
+ * @param offset the offset of the bigram.
+ * @param bigramFrequency the frequency of the bigram, 0..255.
+ * @param unigramFrequency the unigram frequency of the same word, 0..255.
+ * @param word the second bigram, for debugging purposes
* @return the flags
*/
- private static final int makeAttributeFlags(final boolean more, final int offset,
- final int frequency) {
+ private static final int makeBigramFlags(final boolean more, final int offset,
+ int bigramFrequency, final int unigramFrequency, final String word) {
int bigramFlags = (more ? FLAG_ATTRIBUTE_HAS_NEXT : 0)
+ (offset < 0 ? FLAG_ATTRIBUTE_OFFSET_NEGATIVE : 0);
switch (getByteSize(offset)) {
@@ -746,7 +749,21 @@ public class BinaryDictInputOutput {
default:
throw new RuntimeException("Strange offset size");
}
- bigramFlags += frequency & FLAG_ATTRIBUTE_FREQUENCY;
+ if (unigramFrequency > bigramFrequency) {
+ MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
+ + "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
+ + word + " is " + unigramFrequency);
+ bigramFrequency = unigramFrequency;
+ }
+ // We compute the difference between 255 (which means probability = 1) and the
+ // unigram score. We split this into discrete 16 steps, and this is the value
+ // we store into the 4 bits of the bigrams frequency.
+ final float bigramRatio = (float)(bigramFrequency - unigramFrequency)
+ / (MAX_TERMINAL_FREQUENCY - unigramFrequency);
+ // TODO: if the bigram freq is very close to the unigram frequency, we don't want
+ // to include the bigram in the binary dictionary at all.
+ final int discretizedFrequency = Math.round(bigramRatio * MAX_BIGRAM_FREQUENCY);
+ bigramFlags += discretizedFrequency & FLAG_ATTRIBUTE_FREQUENCY;
return bigramFlags;
}
@@ -854,11 +871,14 @@ public class BinaryDictInputOutput {
final Iterator bigramIterator = group.mBigrams.iterator();
while (bigramIterator.hasNext()) {
final WeightedString bigram = (WeightedString)bigramIterator.next();
- final int addressOfBigram = findAddressOfWord(dict, bigram.mWord);
+ final CharGroup target =
+ FusionDictionary.findWordInTree(dict.mRoot, bigram.mWord);
+ final int addressOfBigram = target.mCachedAddress;
+ final int unigramFrequencyForThisWord = target.mFrequency;
++groupAddress;
final int offset = addressOfBigram - groupAddress;
- int bigramFlags = makeAttributeFlags(bigramIterator.hasNext(), offset,
- bigram.mFrequency);
+ int bigramFlags = makeBigramFlags(bigramIterator.hasNext(), offset,
+ bigram.mFrequency, unigramFrequencyForThisWord, bigram.mWord);
buffer[index++] = (byte)bigramFlags;
final int bigramShift = writeVariableAddress(buffer, index, Math.abs(offset));
index += bigramShift;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index f41645283..6f7f0c333 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -23,6 +23,7 @@ import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
import android.util.Log;
import android.util.LruCache;
+import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
@@ -392,7 +393,10 @@ public class AndroidSpellCheckerService extends SpellCheckerService
public DictAndProximity createDictAndProximity(final Locale locale) {
final int script = getScriptFromLocale(locale);
final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo(
- SpellCheckerProximityInfo.getProximityForScript(script));
+ SpellCheckerProximityInfo.getProximityForScript(script),
+ SpellCheckerProximityInfo.ROW_SIZE,
+ SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH,
+ SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT);
final DictionaryCollection dictionaryCollection =
DictionaryFactory.createDictionaryFromManager(this, locale,
true /* useFullEditDistance */);
@@ -484,6 +488,10 @@ public class AndroidSpellCheckerService extends SpellCheckerService
}
mUnigramSuggestionsInfoCache.put(query, new SuggestionsParams(suggestions, flags));
}
+
+ public void remove(String key) {
+ mUnigramSuggestionsInfoCache.remove(key);
+ }
}
AndroidSpellCheckerSession(final AndroidSpellCheckerService service) {
@@ -566,6 +574,96 @@ public class AndroidSpellCheckerService extends SpellCheckerService
return (letterCount * 4 < length * 3);
}
+ private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(
+ TextInfo ti, SentenceSuggestionsInfo ssi) {
+ final String typedText = ti.getText();
+ if (!typedText.contains(SINGLE_QUOTE)) {
+ return null;
+ }
+ final int N = ssi.getSuggestionsCount();
+ final ArrayList<Integer> additionalOffsets = new ArrayList<Integer>();
+ final ArrayList<Integer> additionalLengths = new ArrayList<Integer>();
+ final ArrayList<SuggestionsInfo> additionalSuggestionsInfos =
+ new ArrayList<SuggestionsInfo>();
+ for (int i = 0; i < N; ++i) {
+ final SuggestionsInfo si = ssi.getSuggestionsInfoAt(i);
+ final int flags = si.getSuggestionsAttributes();
+ if ((flags & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) == 0) {
+ continue;
+ }
+ final int offset = ssi.getOffsetAt(i);
+ final int length = ssi.getLengthAt(i);
+ final String subText = typedText.substring(offset, offset + length);
+ if (!subText.contains(SINGLE_QUOTE)) {
+ continue;
+ }
+ final String[] splitTexts = subText.split(SINGLE_QUOTE, -1);
+ if (splitTexts == null || splitTexts.length <= 1) {
+ continue;
+ }
+ final int splitNum = splitTexts.length;
+ for (int j = 0; j < splitNum; ++j) {
+ final String splitText = splitTexts[j];
+ if (TextUtils.isEmpty(splitText)) {
+ continue;
+ }
+ if (mSuggestionsCache.getSuggestionsFromCache(splitText) == null) {
+ continue;
+ }
+ final int newLength = splitText.length();
+ // Neither RESULT_ATTR_IN_THE_DICTIONARY nor RESULT_ATTR_LOOKS_LIKE_TYPO
+ final int newFlags = 0;
+ final SuggestionsInfo newSi = new SuggestionsInfo(newFlags, EMPTY_STRING_ARRAY);
+ newSi.setCookieAndSequence(si.getCookie(), si.getSequence());
+ if (DBG) {
+ Log.d(TAG, "Override and remove old span over: "
+ + splitText + ", " + offset + "," + newLength);
+ }
+ additionalOffsets.add(offset);
+ additionalLengths.add(newLength);
+ additionalSuggestionsInfos.add(newSi);
+ }
+ }
+ final int additionalSize = additionalOffsets.size();
+ if (additionalSize <= 0) {
+ return null;
+ }
+ final int suggestionsSize = N + additionalSize;
+ final int[] newOffsets = new int[suggestionsSize];
+ final int[] newLengths = new int[suggestionsSize];
+ final SuggestionsInfo[] newSuggestionsInfos = new SuggestionsInfo[suggestionsSize];
+ int i;
+ for (i = 0; i < N; ++i) {
+ newOffsets[i] = ssi.getOffsetAt(i);
+ newLengths[i] = ssi.getLengthAt(i);
+ newSuggestionsInfos[i] = ssi.getSuggestionsInfoAt(i);
+ }
+ for (; i < suggestionsSize; ++i) {
+ newOffsets[i] = additionalOffsets.get(i - N);
+ newLengths[i] = additionalLengths.get(i - N);
+ newSuggestionsInfos[i] = additionalSuggestionsInfos.get(i - N);
+ }
+ return new SentenceSuggestionsInfo(newSuggestionsInfos, newOffsets, newLengths);
+ }
+
+ @Override
+ public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(
+ TextInfo[] textInfos, int suggestionsLimit) {
+ final SentenceSuggestionsInfo[] retval = super.onGetSentenceSuggestionsMultiple(
+ textInfos, suggestionsLimit);
+ if (retval == null || retval.length != textInfos.length) {
+ return retval;
+ }
+ for (int i = 0; i < retval.length; ++i) {
+ final SentenceSuggestionsInfo tempSsi =
+ fixWronglyInvalidatedWordWithSingleQuote(textInfos[i], retval[i]);
+ if (tempSsi != null) {
+ retval[i] = tempSsi;
+ }
+ }
+ return retval;
+ }
+
// Note : this must be reentrant
/**
* Gets a list of suggestions for a specific string. This returns a list of possible