diff options
Diffstat (limited to 'java/src')
7 files changed, 98 insertions, 38 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index d5bd7fda3..4a9135310 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -662,10 +662,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { hintY = -mFontMetrics.top + params.mKeyShiftedLetterHintPadding; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() - // The hint label is placed at top-right corner of the key. Used mainly on phone. + // The hint letter is placed at top-right corner of the key. Used mainly on phone. hintX = keyWidth - params.mKeyHintLetterPadding - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2; - hintY = -paint.ascent() + params.mKeyHintLetterPadding; + hintY = -paint.ascent(); paint.setTextAlign(Align.CENTER); } canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java index d0f27a9a8..9dc1786c7 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java @@ -25,7 +25,23 @@ import java.util.HashMap; /** * !!!!! DO NOT EDIT THIS FILE !!!!! - * This file is generated by tools/maketext. + * + * This file is generated by tools/maketext. The base template file is + * tools/maketext/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl + * + * This file must be updated when any text resources in keyboard layout files have been changed. + * These text resources are referred as "!text/<resource_name>" in keyboard XML definitions, + * and should be defined in + * tools/maketext/res/values-<locale>/donottranslate-more-keys.xml + * + * To update this file, please run the following commands. + * $ cd $ANDROID_BUILD_TOP + * $ mmm packages/inputmethods/LatinIME/tools/maketext + * $ maketext -java packages/inputmethods/LatinIME/java/src + * + * The updated source file will be generated to the following path (this file). + * packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/internal/ + * KeyboardTextsSet.java */ public final class KeyboardTextsSet { // Language to texts map. diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java index 613c20304..994b917a7 100644 --- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java @@ -366,6 +366,7 @@ public class AdditionalSubtypeSettings extends PreferenceFragment { final Preference pref = mSubtypePrefGroup.getPreference(i); if (pref instanceof SubtypePreference) { final InputMethodSubtype subtype = ((SubtypePreference)pref).getSubtype(); + if (subtype == null) continue; if (sb.length() > 0) { sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 9429ef411..a644ec0d9 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -83,11 +83,11 @@ public class BinaryDictionary extends Dictionary { private native long openNative(String sourceDir, long dictOffset, long dictSize, int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords); private native void closeNative(long dict); - private native boolean isValidWordNative(long dict, char[] word, int wordLength); + private native boolean isValidWordNative(long dict, int[] word, int wordLength); private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, int[] yCoordinates, int[] inputCodes, int codesSize, int[] prevWordForBigrams, boolean useFullEditDistance, char[] outputChars, int[] scores); - private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength, + private native int getBigramsNative(long dict, int[] prevWord, int prevWordLength, int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, int maxWordLength, int maxBigrams); private static native double calcNormalizedScoreNative( @@ -105,7 +105,7 @@ public class BinaryDictionary extends Dictionary { final WordCallback callback) { if (mNativeDict == 0) return; - char[] chars = previousWord.toString().toCharArray(); + int[] codePoints = StringUtils.toCodePointArray(previousWord.toString()); Arrays.fill(mOutputChars_bigrams, (char) 0); Arrays.fill(mBigramScores, 0); @@ -115,8 +115,8 @@ public class BinaryDictionary extends Dictionary { mInputCodes[0] = codes.getCodeAt(0); } - int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, - mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS); + int count = getBigramsNative(mNativeDict, codePoints, codePoints.length, mInputCodes, + codesSize, mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS); if (count > MAX_BIGRAMS) { count = MAX_BIGRAMS; } @@ -200,7 +200,7 @@ public class BinaryDictionary extends Dictionary { @Override public boolean isValidWord(CharSequence word) { if (word == null) return false; - char[] chars = word.toString().toCharArray(); + int[] chars = StringUtils.toCodePointArray(word.toString()); return isValidWordNative(mNativeDict, chars, chars.length); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index e1978fca1..c6381180c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1793,6 +1793,24 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void pickSuggestionManually(final int index, final CharSequence suggestion, int x, int y) { final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); + final InputConnection ic = getCurrentInputConnection(); + if (ic != null) ic.beginBatchEdit(); + + // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput + if (suggestion.length() == 1 && isShowingPunctuationList()) { + // Word separators are suggested before the user inputs something. + // So, LatinImeLogger logs "" as a user's input. + LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); + // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y); + } + final int primaryCode = suggestion.charAt(0); + onCodeInput(primaryCode, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); + return; + } if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { int firstChar = Character.codePointAt(suggestion, 0); @@ -1810,7 +1828,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mKeyboardSwitcher.updateShiftState(); resetComposingState(true /* alsoResetLastComposedWord */); - final InputConnection ic = getCurrentInputConnection(); if (ic != null) { final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; ic.commitCompletion(completionInfo); @@ -1822,21 +1839,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return; } - // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput - if (suggestion.length() == 1 && isShowingPunctuationList()) { - // Word separators are suggested before the user inputs something. - // So, LatinImeLogger logs "" as a user's input. - LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); - // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. - if (ProductionFlag.IS_EXPERIMENTAL) { - ResearchLogger.latinIME_punctuationSuggestion(index, suggestion, x, y); - } - final int primaryCode = suggestion.charAt(0); - onCodeInput(primaryCode, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); - return; - } // We need to log before we commit, because the word composer will store away the user // typed word. final String replacedWord = mWordComposer.getTypedWord().toString(); @@ -1889,6 +1891,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.postUpdateSuggestions(); } } + if (null != ic) ic.endBatchEdit(); } /** diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 97df98e34..cc98010fb 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -174,6 +174,13 @@ public class BinaryDictInputOutput { private static final int MAX_TERMINAL_FREQUENCY = 255; + // Arbitrary limit to how much passes we consider address size compression should + // terminate in. At the time of this writing, our largest dictionary completes + // compression in five passes. + // If the number of passes exceeds this number, makedict bails with an exception on + // suspicion that a bug might be causing an infinite loop. + private static final int MAX_PASSES = 24; + /** * A class grouping utility function for our specific character encoding. */ @@ -510,14 +517,22 @@ public class BinaryDictInputOutput { * Each node stores its tentative address. During dictionary address computing, these * are not final, but they can be used to compute the node size (the node size depends * on the address of the children because the number of bytes necessary to store an - * address depends on its numeric value. + * address depends on its numeric value. The return value indicates whether the node + * contents (as in, any of the addresses stored in the cache fields) have changed with + * respect to their previous value. * * @param node the node to compute the size of. * @param dict the dictionary in which the word/attributes are to be found. + * @return false if none of the cached addresses inside the node changed, true otherwise. */ - private static void computeActualNodeSize(Node node, FusionDictionary dict) { + private static boolean computeActualNodeSize(Node node, FusionDictionary dict) { + boolean changed = false; int size = getGroupCountSize(node); for (CharGroup group : node.mData) { + if (group.mCachedAddress != node.mCachedAddress + size) { + changed = true; + group.mCachedAddress = node.mCachedAddress + size; + } int groupSize = GROUP_FLAGS_SIZE + getGroupCharactersSize(group); if (group.isTerminal()) groupSize += GROUP_FREQUENCY_SIZE; if (null != group.mChildren) { @@ -538,7 +553,11 @@ public class BinaryDictInputOutput { group.mCachedSize = groupSize; size += groupSize; } - node.mCachedSize = size; + if (node.mCachedSize != size) { + node.mCachedSize = size; + changed = true; + } + return changed; } /** @@ -594,13 +613,14 @@ public class BinaryDictInputOutput { changesDone = false; for (Node n : flatNodes) { final int oldNodeSize = n.mCachedSize; - computeActualNodeSize(n, dict); + final boolean changed = computeActualNodeSize(n, dict); final int newNodeSize = n.mCachedSize; if (oldNodeSize < newNodeSize) throw new RuntimeException("Increased size ?!"); - if (oldNodeSize != newNodeSize) changesDone = true; + changesDone |= changed; } stackNodes(flatNodes); ++passes; + if (passes > MAX_PASSES) throw new RuntimeException("Too many passes - probably a bug"); } while (changesDone); final Node lastNode = flatNodes.get(flatNodes.size() - 1); @@ -1122,6 +1142,12 @@ public class BinaryDictInputOutput { } } + // The word cache here is a stopgap bandaid to help the catastrophic performance + // of this method. Since it performs direct, unbuffered random access to the file and + // may be called hundreds of thousands of times, the resulting performance is not + // reasonable without some kind of cache. Thus: + // TODO: perform buffered I/O here and in other places in the code. + private static TreeMap<Integer, String> wordCache = new TreeMap<Integer, String>(); /** * Finds, as a string, the word at the address passed as an argument. * @@ -1131,8 +1157,10 @@ public class BinaryDictInputOutput { * @return the word, as a string. * @throws IOException if the file can't be read. */ - private static String getWordAtAddress(RandomAccessFile source, long headerSize, + private static String getWordAtAddress(final RandomAccessFile source, final long headerSize, int address) throws IOException { + final String cachedString = wordCache.get(address); + if (null != cachedString) return cachedString; final long originalPointer = source.getFilePointer(); source.seek(headerSize); final int count = readCharGroupCount(source); @@ -1171,6 +1199,7 @@ public class BinaryDictInputOutput { } } source.seek(originalPointer); + wordCache.put(address, result); return result; } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index a17371396..26a9415c4 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -171,7 +171,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public boolean mMoreSuggestionsAvailable; - public final TextView mWordToSaveView; + private final TextView mWordToSaveView; private final TextView mLeftwardsArrowView; private final TextView mHintToSaveView; @@ -477,7 +477,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView, - int stripWidth, CharSequence hintText) { + int stripWidth, CharSequence hintText, OnClickListener listener) { final int width = stripWidth - mDividerWidth - mPadding * 2; final TextView wordView = mWordToSaveView; @@ -508,6 +508,18 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, stripView.addView(hintView); setLayoutWeight( hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); + + wordView.setOnClickListener(listener); + leftArrowView.setOnClickListener(listener); + hintView.setOnClickListener(listener); + } + + public CharSequence getAddToDictionaryWord() { + return (CharSequence)mWordToSaveView.getTag(); + } + + public boolean isAddToDictionaryShowing(View v) { + return v == mWordToSaveView || v == mHintToSaveView || v == mLeftwardsArrowView; } private static void setLayoutWeight(View v, float weight, int height) { @@ -620,7 +632,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } mParams = new SuggestionsViewParams(context, attrs, defStyle, mWords, mDividers, mInfos); - mParams.mWordToSaveView.setOnClickListener(this); mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null); mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer @@ -676,12 +687,12 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public boolean isShowingAddToDictionaryHint() { return mSuggestionsStrip.getChildCount() > 0 - && mSuggestionsStrip.getChildAt(0) == mParams.mWordToSaveView; + && mParams.isAddToDictionaryShowing(mSuggestionsStrip.getChildAt(0)); } public void showAddToDictionaryHint(CharSequence word, CharSequence hintText) { clear(); - mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText); + mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText, this); } public boolean dismissAddToDictionaryHint() { @@ -851,8 +862,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, @Override public void onClick(View view) { - if (view == mParams.mWordToSaveView) { - addToDictionary((CharSequence)view.getTag()); + if (mParams.isAddToDictionaryShowing(view)) { + addToDictionary(mParams.getAddToDictionaryWord()); clear(); return; } |