aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java15
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java31
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java7
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java21
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java4
-rw-r--r--java/src/com/android/inputmethod/latin/StringUtils.java19
-rw-r--r--java/src/com/android/inputmethod/latin/Utils.java2
-rw-r--r--java/src/com/android/inputmethod/latin/define/ProductionFlag.java1
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java34
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FormatSpec.java30
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java7
11 files changed, 116 insertions, 55 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 9a888ade4..9764df072 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -28,7 +28,7 @@ import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
@@ -357,14 +357,15 @@ class BinaryDictionaryGetter {
try {
// Read the version of the file
inStream = new FileInputStream(f);
- final ByteBuffer buffer = inStream.getChannel().map(
- FileChannel.MapMode.READ_ONLY, 0, f.length());
- final int magic = buffer.getInt();
+ final BinaryDictInputOutput.ByteBufferWrapper buffer =
+ new BinaryDictInputOutput.ByteBufferWrapper(inStream.getChannel().map(
+ FileChannel.MapMode.READ_ONLY, 0, f.length()));
+ final int magic = buffer.readInt();
if (magic != FormatSpec.VERSION_2_MAGIC_NUMBER) {
return false;
}
- final int formatVersion = buffer.getInt();
- final int headerSize = buffer.getInt();
+ final int formatVersion = buffer.readInt();
+ final int headerSize = buffer.readInt();
final HashMap<String, String> options = CollectionUtils.newHashMap();
BinaryDictInputOutput.populateOptions(buffer, headerSize, options);
@@ -382,6 +383,8 @@ class BinaryDictionaryGetter {
return false;
} catch (NumberFormatException e) {
return false;
+ } catch (BufferUnderflowException e) {
+ return false;
} finally {
if (inStream != null) {
try {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index db8f269eb..10a6e9544 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -741,6 +741,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// switcher.loadKeyboard; in apps like Talk, we come here when the text is sent and the
// field gets emptied and we need to re-evaluate the shift state, but not the whole layout
// which would be disruptive.
+ // Space state must be updated before calling updateShiftState
mKeyboardSwitcher.updateShiftState();
mHandler.cancelUpdateSuggestionStrip();
@@ -1100,25 +1101,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
-
final int inputType = ei.inputType;
- if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
- return TextUtils.CAP_MODE_CHARACTERS;
- }
-
- final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
- | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
- if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF;
-
- // Avoid making heavy round-trip IPC calls of {@link InputConnection#getCursorCapsMode}
- // unless needed.
- if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF;
-
- // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
- // Note: getCursorCapsMode() returns the current capitalization mode that is any
- // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none
- // of them.
- return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale());
+ // Warning: this depends on mSpaceState, which may not be the most current value. If
+ // mSpaceState gets updated later, whoever called this may need to be told about it.
+ return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale(),
+ SPACE_STATE_PHANTOM == mSpaceState);
}
// Factor in auto-caps and manual caps and compute the current caps mode.
@@ -1391,9 +1378,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
mConnection.commitText(text, 1);
mConnection.endBatchEdit();
+ // Space state must be updated before calling updateShiftState
+ mSpaceState = SPACE_STATE_NONE;
mKeyboardSwitcher.updateShiftState();
mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
- mSpaceState = SPACE_STATE_NONE;
mEnteredText = text;
}
@@ -1509,8 +1497,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mConnection.setComposingText(batchInputText, 1);
mExpectingUpdateSelection = true;
mConnection.endBatchEdit();
- mKeyboardSwitcher.updateShiftState();
+ // Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_PHANTOM;
+ mKeyboardSwitcher.updateShiftState();
}
private CharSequence specificTldProcessingOnTextInput(final CharSequence text) {
@@ -2019,8 +2008,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mConnection.endBatchEdit();
// Don't allow cancellation of manual pick
mLastComposedWord.deactivate();
+ // Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_PHANTOM;
- // TODO: is this necessary?
mKeyboardSwitcher.updateShiftState();
// We should show the "Touch again to save" hint if the user pressed the first entry
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index e843848bc..a5b4c68d0 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -44,7 +44,12 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
String before, String after, int position, SuggestedWords suggestedWords) {
}
- public static void logOnAutoCorrection(String before, String after, int separatorCode) {
+ public static void logOnAutoCorrectionForTyping(
+ String before, String after, int separatorCode) {
+ }
+
+ public static void logOnAutoCorrectionForGeometric(String before, String after,
+ int separatorCode, int[] xCoordinates, int[] yCoordinates, int[] relativeTimes) {
}
public static void logOnAutoCorrectionCancelled() {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index b85f9dcd7..cbc6a93fa 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -190,7 +190,23 @@ public class RichInputConnection {
}
}
- public int getCursorCapsMode(final int inputType, final Locale locale) {
+ /**
+ * Gets the caps modes we should be in after this specific string.
+ *
+ * This returns a bit set of TextUtils#CAP_MODE_*, masked by the inputType argument.
+ * This method also supports faking an additional space after the string passed in argument,
+ * to support cases where a space will be added automatically, like in phantom space
+ * state for example.
+ * Note that for English, we are using American typography rules (which are not specific to
+ * American English, it's just the most common set of rules for English).
+ *
+ * @param inputType a mask of the caps modes to test for.
+ * @param locale what language should be considered.
+ * @param hasSpaceBefore if we should consider there should be a space after the string.
+ * @return the caps modes that should be on as a set of bits
+ */
+ public int getCursorCapsMode(final int inputType, final Locale locale,
+ final boolean hasSpaceBefore) {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
if (!TextUtils.isEmpty(mComposingText)) return Constants.TextUtils.CAP_MODE_OFF;
@@ -205,7 +221,8 @@ public class RichInputConnection {
}
// This never calls InputConnection#getCapsMode - in fact, it's a static method that
// never blocks or initiates IPC.
- return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale);
+ return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale,
+ hasSpaceBefore);
}
public CharSequence getTextBeforeCursor(final int i, final int j) {
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 6251c9acd..180f6c56f 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -44,7 +44,7 @@ import com.android.inputmethodcommon.InputMethodSettingsFragment;
public class Settings extends InputMethodSettingsFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
- public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false;
+ public static final boolean ENABLE_INTERNAL_SETTINGS = ProductionFlag.IS_INTERNAL;
// In the same order as xml/prefs.xml
public static final String PREF_GENERAL_SETTINGS = "general_settings";
@@ -220,7 +220,7 @@ public class Settings extends InputMethodSettingsFragment
final boolean showUsabilityStudyModeOption =
res.getBoolean(R.bool.config_enable_usability_study_mode_option)
- || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS;
+ || ProductionFlag.IS_EXPERIMENTAL || ENABLE_INTERNAL_SETTINGS;
final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE);
if (!showUsabilityStudyModeOption) {
if (usabilityStudyPref != null) {
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 6dc1ea807..7b65b7343 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -197,13 +197,15 @@ public final class StringUtils {
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}.
* @param locale The locale to consider for capitalization rules
+ * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs
*
* @return Returns the actual capitalization modes that can be in effect
* at the current position, which is any combination of
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}.
*/
- public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale) {
+ public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale,
+ final boolean hasSpaceBefore) {
// Quick description of what we want to do:
// CAP_MODE_CHARACTERS is always on.
// CAP_MODE_WORDS is on if there is some whitespace before the cursor.
@@ -230,11 +232,15 @@ public final class StringUtils {
// single quote since they aren't start punctuation in the unicode sense, but should still
// be skipped for English. TODO: does this depend on the language?
int i;
- for (i = cs.length(); i > 0; i--) {
- final char c = cs.charAt(i - 1);
- if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE
- && Character.getType(c) != Character.START_PUNCTUATION) {
- break;
+ if (hasSpaceBefore) {
+ i = cs.length() + 1;
+ } else {
+ for (i = cs.length(); i > 0; i--) {
+ final char c = cs.charAt(i - 1);
+ if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE
+ && Character.getType(c) != Character.START_PUNCTUATION) {
+ break;
+ }
}
}
@@ -247,6 +253,7 @@ public final class StringUtils {
// if the first char that's not a space or tab is a start of line (as in, either \n or
// start of text).
int j = i;
+ if (hasSpaceBefore) --j;
while (j > 0 && Character.isWhitespace(cs.charAt(j - 1))) {
j--;
}
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 1c98b92cd..63b642821 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -419,7 +419,7 @@ public final class Utils {
// smileys and other multi-character keys.
final int codePoint = TextUtils.isEmpty(separatorString) ? Constants.NOT_A_CODE
: separatorString.codePointAt(0);
- LatinImeLogger.logOnAutoCorrection(typedWord, correctedWord, codePoint);
+ LatinImeLogger.logOnAutoCorrectionForTyping(typedWord, correctedWord, codePoint);
}
public static void onAutoCorrectionCancellation() {
diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
index de2057669..52c066a44 100644
--- a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
+++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java
@@ -22,4 +22,5 @@ public final class ProductionFlag {
}
public static final boolean IS_EXPERIMENTAL = false;
+ public static final boolean IS_INTERNAL = false;
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index 6f508695e..72d12299b 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -370,6 +370,9 @@ public class BinaryDictInputOutput {
g.mCachedSize = groupSize;
size += groupSize;
}
+ if (options.mHasLinkedListNode) {
+ size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
+ }
node.mCachedSize = size;
}
@@ -521,6 +524,9 @@ public class BinaryDictInputOutput {
group.mCachedSize = groupSize;
size += groupSize;
}
+ if (formatOptions.mHasLinkedListNode) {
+ size += FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
+ }
if (node.mCachedSize != size) {
node.mCachedSize = size;
changed = true;
@@ -532,9 +538,11 @@ public class BinaryDictInputOutput {
* Computes the byte size of a list of nodes and updates each node cached position.
*
* @param flatNodes the array of nodes.
+ * @param formatOptions file format options.
* @return the byte size of the entire stack.
*/
- private static int stackNodes(final ArrayList<Node> flatNodes) {
+ private static int stackNodes(final ArrayList<Node> flatNodes,
+ final FormatOptions formatOptions) {
int nodeOffset = 0;
for (Node n : flatNodes) {
n.mCachedAddress = nodeOffset;
@@ -544,7 +552,9 @@ public class BinaryDictInputOutput {
g.mCachedAddress = groupCountSize + nodeOffset + groupOffset;
groupOffset += g.mCachedSize;
}
- if (groupOffset + groupCountSize != n.mCachedSize) {
+ final int nodeSize = groupCountSize + groupOffset
+ + (formatOptions.mHasLinkedListNode ? FormatSpec.FORWARD_LINK_ADDRESS_SIZE : 0);
+ if (nodeSize != n.mCachedSize) {
throw new RuntimeException("Bug : Stored and computed node size differ");
}
nodeOffset += n.mCachedSize;
@@ -571,7 +581,7 @@ public class BinaryDictInputOutput {
final ArrayList<Node> flatNodes, final FormatOptions formatOptions) {
// First get the worst sizes and offsets
for (Node n : flatNodes) setNodeMaximumSize(n, formatOptions);
- final int offset = stackNodes(flatNodes);
+ final int offset = stackNodes(flatNodes, formatOptions);
MakedictLog.i("Compressing the array addresses. Original size : " + offset);
MakedictLog.i("(Recursively seen size : " + offset + ")");
@@ -587,7 +597,7 @@ public class BinaryDictInputOutput {
if (oldNodeSize < newNodeSize) throw new RuntimeException("Increased size ?!");
changesDone |= changed;
}
- stackNodes(flatNodes);
+ stackNodes(flatNodes, formatOptions);
++passes;
if (passes > MAX_PASSES) throw new RuntimeException("Too many passes - probably a bug");
} while (changesDone);
@@ -776,7 +786,8 @@ public class BinaryDictInputOutput {
return (options.mFrenchLigatureProcessing ? FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG : 0)
+ (options.mGermanUmlautProcessing ? FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG : 0)
+ (hasBigrams ? FormatSpec.CONTAINS_BIGRAMS_FLAG : 0)
- + (formatOptions.mHasParentAddress ? FormatSpec.HAS_PARENT_ADDRESS : 0);
+ + (formatOptions.mHasParentAddress ? FormatSpec.HAS_PARENT_ADDRESS : 0)
+ + (formatOptions.mHasLinkedListNode ? FormatSpec.HAS_LINKEDLIST_NODE : 0);
}
/**
@@ -910,6 +921,11 @@ public class BinaryDictInputOutput {
}
}
+ if (formatOptions.mHasLinkedListNode) {
+ buffer[index] = buffer[index + 1] = buffer[index + 2]
+ = FormatSpec.NO_FORWARD_LINK_ADDRESS;
+ index += FormatSpec.FORWARD_LINK_ADDRESS_SIZE;
+ }
if (index != node.mCachedAddress + node.mCachedSize) throw new RuntimeException(
"Not the same size : written "
+ (index - node.mCachedAddress) + " bytes out of a node that should have "
@@ -1525,7 +1541,8 @@ public class BinaryDictInputOutput {
0 != (optionsFlags & FormatSpec.GERMAN_UMLAUT_PROCESSING_FLAG),
0 != (optionsFlags & FormatSpec.FRENCH_LIGATURE_PROCESSING_FLAG)),
new FormatOptions(version,
- 0 != (optionsFlags & FormatSpec.HAS_PARENT_ADDRESS)));
+ 0 != (optionsFlags & FormatSpec.HAS_PARENT_ADDRESS),
+ 0 != (optionsFlags & FormatSpec.HAS_LINKEDLIST_NODE)));
return header;
}
@@ -1543,11 +1560,6 @@ public class BinaryDictInputOutput {
options.put(key, value);
}
}
- // TODO: remove this method.
- public static void populateOptions(final ByteBuffer buffer, final int headerSize,
- final HashMap<String, String> options) {
- populateOptions(new ByteBufferWrapper(buffer), headerSize, options);
- }
/**
* Reads a buffer and returns the memory representation of the dictionary.
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index 1707ccc39..f8f13b197 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -41,6 +41,12 @@ public final class FormatSpec {
* u |
* ps
*
+ * f |
+ * o | IF HAS_LINKEDLIST_NODE (defined in the file header)
+ * r | forward link address, 3byte
+ * w | the address must be positive.
+ * a |
+ * rdlinkaddress
*/
/* Node(CharGroup) layout is as follows:
@@ -140,18 +146,23 @@ public final class FormatSpec {
static final int NOT_A_VERSION_NUMBER = -1;
static final int FIRST_VERSION_WITH_HEADER_SIZE = 2;
static final int FIRST_VERSION_WITH_PARENT_ADDRESS = 3;
+ static final int FIRST_VERSION_WITH_LINKEDLIST_NODE = 3;
// These options need to be the same numeric values as the one in the native reading code.
static final int GERMAN_UMLAUT_PROCESSING_FLAG = 0x1;
+ // TODO: Make the native reading code read this variable.
static final int HAS_PARENT_ADDRESS = 0x2;
static final int FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
static final int CONTAINS_BIGRAMS_FLAG = 0x8;
+ // TODO: Make the native reading code read this variable.
+ static final int HAS_LINKEDLIST_NODE = 0x10;
// TODO: Make this value adaptative to content data, store it in the header, and
// use it in the reading code.
static final int MAX_WORD_LENGTH = Constants.Dictionary.MAX_WORD_LENGTH;
static final int PARENT_ADDRESS_SIZE = 3;
+ static final int FORWARD_LINK_ADDRESS_SIZE = 3;
static final int MASK_GROUP_ADDRESS_TYPE = 0xC0;
static final int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00;
@@ -187,6 +198,7 @@ public final class FormatSpec {
static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
static final int NO_PARENT_ADDRESS = 0;
+ static final int NO_FORWARD_LINK_ADDRESS = 0;
static final int INVALID_CHARACTER = -1;
static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127
@@ -201,16 +213,30 @@ public final class FormatSpec {
public static class FormatOptions {
public final int mVersion;
public final boolean mHasParentAddress;
+ public final boolean mHasLinkedListNode;
public FormatOptions(final int version) {
this(version, false);
}
public FormatOptions(final int version, final boolean hasParentAddress) {
+ this(version, hasParentAddress, false);
+ }
+ public FormatOptions(final int version, final boolean hasParentAddress,
+ final boolean hasLinkedListNode) {
mVersion = version;
- if (version < FormatSpec.FIRST_VERSION_WITH_PARENT_ADDRESS && hasParentAddress) {
+ if (version < FIRST_VERSION_WITH_PARENT_ADDRESS && hasParentAddress) {
throw new RuntimeException("Parent addresses are only supported with versions "
- + FormatSpec.FIRST_VERSION_WITH_PARENT_ADDRESS + " and ulterior.");
+ + FIRST_VERSION_WITH_PARENT_ADDRESS + " and ulterior.");
}
mHasParentAddress = hasParentAddress;
+
+ if (version < FIRST_VERSION_WITH_LINKEDLIST_NODE && hasLinkedListNode) {
+ throw new RuntimeException("Linked list nodes are only supported with versions "
+ + FIRST_VERSION_WITH_LINKEDLIST_NODE + " and ulterior.");
+ }
+ if (!hasParentAddress && hasLinkedListNode) {
+ throw new RuntimeException("Linked list nodes need parent addresses.");
+ }
+ mHasLinkedListNode = hasLinkedListNode;
}
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index 6775de8a8..98cf308c8 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -556,6 +556,7 @@ public class FusionDictionary implements Iterable<Word> {
final StringBuilder checker = DBG ? new StringBuilder() : null;
CharGroup currentGroup;
+ final int codePointCountInS = s.codePointCount(0, s.length());
do {
int indexOfGroup = findIndexOfChar(node, s.codePointAt(index));
if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
@@ -570,12 +571,12 @@ public class FusionDictionary implements Iterable<Word> {
index = newIndex;
if (DBG) checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
- if (index < s.length()) {
+ if (index < codePointCountInS) {
node = currentGroup.mChildren;
}
- } while (null != node && index < s.length());
+ } while (null != node && index < codePointCountInS);
- if (index < s.length()) return null;
+ if (index < codePointCountInS) return null;
if (!currentGroup.isTerminal()) return null;
if (DBG && !s.equals(checker.toString())) return null;
return currentGroup;