Merge "Import translations. DO NOT MERGE"
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index b55e19d..99c44f4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -519,7 +519,7 @@
         // U+061F: "؟" ARABIC QUESTION MARK
         // U+060C: "،" ARABIC COMMA
         // U+061B: "؛" ARABIC SEMICOLON
-        /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+        /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
         /* 54 */ "\u2605,\u066D",
@@ -1408,7 +1408,7 @@
         // U+061F: "؟" ARABIC QUESTION MARK
         // U+060C: "،" ARABIC COMMA
         // U+061B: "؛" ARABIC SEMICOLON
-        /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(,)",
+        /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\u060C,\u061F,@,&,\\%,+,\u061B,/,(|),)|(",
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
         /* 54 */ "\u2605,\u066D",
@@ -1900,8 +1900,9 @@
         /* 48 */ "!text/single_laqm_raqm_rtl",
         /* 49 */ "!text/double_laqm_raqm_rtl",
         /* 50~ */
-        null, null, null, null,
-        /* ~53 */
+        null, null, null,
+        /* ~52 */
+        /* 53 */ "!fixedColumnOrder!8,\",\',#,-,:,!,\\,,?,@,&,\\%,+,;,/,(|),)|(",
         // U+2605: "★" BLACK STAR
         /* 54 */ "\u2605",
         /* 55 */ null,
diff --git a/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
index b2e979d..a8600c0 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DynamicPredictionDictionaryBase.java
@@ -404,6 +404,7 @@
     public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) {
         session.setPredictionDictionary(mLocale, this);
         mSessions.add(session);
+        session.onDictionaryReady();
     }
 
     public void unRegisterUpdateSession(PersonalizationDictionaryUpdateSession session) {
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
index 0e8d72f..15f2aa6 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.cpp
@@ -16,6 +16,8 @@
 
 #include "suggest/core/dictionary/binary_dictionary_format_utils.h"
 
+#include "suggest/core/dictionary/byte_array_utils.h"
+
 namespace latinime {
 
 /**
@@ -27,7 +29,6 @@
 /**
  * Format versions
  */
-
 // The versions of Latin IME that only handle format version 1 only test for the magic
 // number, so we had to change it so that version 2 files would be rejected by older
 // implementations. On this occasion, we made the magic number 32 bits long.
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.h
index 830684c..62c7376 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_format_utils.h
@@ -20,7 +20,6 @@
 #include <stdint.h>
 
 #include "defines.h"
-#include "suggest/core/dictionary/byte_array_utils.h"
 
 namespace latinime {
 
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
index 91c643a..16f534c 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.cpp
@@ -17,7 +17,6 @@
 #include "suggest/core/dictionary/binary_dictionary_header.h"
 
 #include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_info.h"
 
 namespace latinime {
 
@@ -26,16 +25,15 @@
 const float BinaryDictionaryHeader::DEFAULT_MULTI_WORD_COST_MULTIPLIER = 1.0f;
 const float BinaryDictionaryHeader::MULTI_WORD_COST_MULTIPLIER_SCALE = 100.0f;
 
-BinaryDictionaryHeader::BinaryDictionaryHeader(
-        const BinaryDictionaryInfo *const binaryDictionaryInfo)
-        : mBinaryDictionaryInfo(binaryDictionaryInfo),
-          mDictionaryFlags(BinaryDictionaryHeaderReadingUtils::getFlags(binaryDictionaryInfo)),
-          mSize(BinaryDictionaryHeaderReadingUtils::getHeaderSize(binaryDictionaryInfo)),
+BinaryDictionaryHeader::BinaryDictionaryHeader(const uint8_t *const dictBuf)
+        : mDictBuf(dictBuf),
+          mDictionaryFlags(BinaryDictionaryHeaderReadingUtils::getFlags(mDictBuf)),
+          mSize(BinaryDictionaryHeaderReadingUtils::getHeaderSize(mDictBuf)),
           mMultiWordCostMultiplier(readMultiWordCostMultiplier()) {}
 
 float BinaryDictionaryHeader::readMultiWordCostMultiplier() const {
     const int headerValue = BinaryDictionaryHeaderReadingUtils::readHeaderValueInt(
-            mBinaryDictionaryInfo, MULTIPLE_WORDS_DEMOTION_RATE_KEY);
+            mDictBuf, MULTIPLE_WORDS_DEMOTION_RATE_KEY);
     if (headerValue == S_INT_MIN) {
         // not found
         return DEFAULT_MULTI_WORD_COST_MULTIPLIER;
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
index 240512b..4d92952 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header.h
@@ -17,6 +17,8 @@
 #ifndef LATINIME_BINARY_DICTIONARY_HEADER_H
 #define LATINIME_BINARY_DICTIONARY_HEADER_H
 
+#include <stdint.h>
+
 #include "defines.h"
 #include "suggest/core/dictionary/binary_dictionary_header_reading_utils.h"
 
@@ -28,9 +30,10 @@
  * This class abstracts dictionary header structures and provide interface to access dictionary
  * header information.
  */
+// TODO:: Move header classes to policyimpl.
 class BinaryDictionaryHeader {
  public:
-    explicit BinaryDictionaryHeader(const BinaryDictionaryInfo *const binaryDictionaryInfo);
+    explicit BinaryDictionaryHeader(const uint8_t *const dictBuf);
 
     AK_FORCE_INLINE int getSize() const {
         return mSize;
@@ -60,7 +63,7 @@
             outValue[0] = '\0';
             return;
         }
-        if (!BinaryDictionaryHeaderReadingUtils::readHeaderValue(mBinaryDictionaryInfo,
+        if (!BinaryDictionaryHeaderReadingUtils::readHeaderValue(mDictBuf,
                 key, outValue, outValueSize)) {
             outValue[0] = '?';
             outValue[1] = '\0';
@@ -74,7 +77,7 @@
     static const float DEFAULT_MULTI_WORD_COST_MULTIPLIER;
     static const float MULTI_WORD_COST_MULTIPLIER_SCALE;
 
-    const BinaryDictionaryInfo *const mBinaryDictionaryInfo;
+    const uint8_t *const mDictBuf;
     const BinaryDictionaryHeaderReadingUtils::DictionaryFlags mDictionaryFlags;
     const int mSize;
     const float mMultiWordCostMultiplier;
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
index a57b0f8..bcf0e61 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.cpp
@@ -20,12 +20,11 @@
 #include <cstdlib>
 
 #include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_info.h"
+#include "suggest/core/dictionary/byte_array_utils.h"
 
 namespace latinime {
 
 const int BinaryDictionaryHeaderReadingUtils::MAX_OPTION_KEY_LENGTH = 256;
-
 const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_MAGIC_NUMBER_SIZE = 4;
 const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_DICTIONARY_VERSION_SIZE = 2;
 const int BinaryDictionaryHeaderReadingUtils::VERSION_2_HEADER_FLAG_SIZE = 2;
@@ -43,68 +42,54 @@
 const BinaryDictionaryHeaderReadingUtils::DictionaryFlags
         BinaryDictionaryHeaderReadingUtils::FRENCH_LIGATURE_PROCESSING_FLAG = 0x4;
 
-/* static */ int BinaryDictionaryHeaderReadingUtils::getHeaderSize(
-        const BinaryDictionaryInfo *const binaryDictionaryInfo) {
-    switch (getHeaderVersion(binaryDictionaryInfo->getFormat())) {
-        case HEADER_VERSION_2:
-            // See the format of the header in the comment in
-            // BinaryDictionaryFormatUtils::detectFormatVersion()
-            return ByteArrayUtils::readUint32(binaryDictionaryInfo->getDictBuf(),
-                    VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
-                            + VERSION_2_HEADER_FLAG_SIZE);
-        default:
-            return S_INT_MAX;
-    }
+/* static */ int BinaryDictionaryHeaderReadingUtils::getHeaderSize(const uint8_t *const dictBuf) {
+    // See the format of the header in the comment in
+    // BinaryDictionaryFormatUtils::detectFormatVersion()
+    return ByteArrayUtils::readUint32(dictBuf,
+            VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
+                    + VERSION_2_HEADER_FLAG_SIZE);
 }
 
 /* static */ BinaryDictionaryHeaderReadingUtils::DictionaryFlags
-        BinaryDictionaryHeaderReadingUtils::getFlags(
-                const BinaryDictionaryInfo *const binaryDictionaryInfo) {
-    switch (getHeaderVersion(binaryDictionaryInfo->getFormat())) {
-        case HEADER_VERSION_2:
-            return ByteArrayUtils::readUint16(binaryDictionaryInfo->getDictBuf(),
-                    VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE);
-        default:
-            return NO_FLAGS;
-    }
+        BinaryDictionaryHeaderReadingUtils::getFlags(const uint8_t *const dictBuf) {
+    return ByteArrayUtils::readUint16(dictBuf, VERSION_2_HEADER_MAGIC_NUMBER_SIZE
+            + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE);
 }
 
 // Returns if the key is found or not and reads the found value into outValue.
-/* static */ bool BinaryDictionaryHeaderReadingUtils::readHeaderValue(
-        const BinaryDictionaryInfo *const binaryDictionaryInfo,
+/* static */ bool BinaryDictionaryHeaderReadingUtils::readHeaderValue(const uint8_t *const dictBuf,
         const char *const key, int *outValue, const int outValueSize) {
     if (outValueSize <= 0) {
         return false;
     }
-    const int headerSize = getHeaderSize(binaryDictionaryInfo);
-    int pos = getHeaderOptionsPosition(binaryDictionaryInfo->getFormat());
+    const int headerSize = getHeaderSize(dictBuf);
+    int pos = getHeaderOptionsPosition();
     if (pos == NOT_A_DICT_POS) {
         // The header doesn't have header options.
         return false;
     }
     while (pos < headerSize) {
         if(ByteArrayUtils::compareStringInBufferWithCharArray(
-                binaryDictionaryInfo->getDictBuf(), key, headerSize - pos, &pos) == 0) {
+                dictBuf, key, headerSize - pos, &pos) == 0) {
             // The key was found.
             const int length = ByteArrayUtils::readStringAndAdvancePosition(
-                    binaryDictionaryInfo->getDictBuf(), outValueSize, outValue, &pos);
+                    dictBuf, outValueSize, outValue, &pos);
             // Add a 0 terminator to the string.
             outValue[length < outValueSize ? length : outValueSize - 1] = '\0';
             return true;
         }
-        ByteArrayUtils::advancePositionToBehindString(
-                binaryDictionaryInfo->getDictBuf(), headerSize - pos, &pos);
+        ByteArrayUtils::advancePositionToBehindString(dictBuf, headerSize - pos, &pos);
     }
     // The key was not found.
     return false;
 }
 
 /* static */ int BinaryDictionaryHeaderReadingUtils::readHeaderValueInt(
-        const BinaryDictionaryInfo *const binaryDictionaryInfo, const char *const key) {
+        const uint8_t *const dictBuf, const char *const key) {
     const int bufferSize = LARGEST_INT_DIGIT_COUNT;
     int intBuffer[bufferSize];
     char charBuffer[bufferSize];
-    if (!readHeaderValue(binaryDictionaryInfo, key, intBuffer, bufferSize)) {
+    if (!readHeaderValue(dictBuf, key, intBuffer, bufferSize)) {
         return S_INT_MIN;
     }
     for (int i = 0; i < bufferSize; ++i) {
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
index 6174822..deae9be 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_header_reading_utils.h
@@ -20,21 +20,19 @@
 #include <stdint.h>
 
 #include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_format_utils.h"
 
 namespace latinime {
 
-class BinaryDictionaryInfo;
-
+// TODO:: Move header classes to policyimpl.
 class BinaryDictionaryHeaderReadingUtils {
  public:
     typedef uint16_t DictionaryFlags;
 
     static const int MAX_OPTION_KEY_LENGTH;
 
-    static int getHeaderSize(const BinaryDictionaryInfo *const binaryDictionaryInfo);
+    static int getHeaderSize(const uint8_t *const dictBuf);
 
-    static DictionaryFlags getFlags(const BinaryDictionaryInfo *const binaryDictionaryInfo);
+    static DictionaryFlags getFlags(const uint8_t *const dictBuf);
 
     static AK_FORCE_INLINE bool supportsDynamicUpdate(const DictionaryFlags flags) {
         return (flags & SUPPORTS_DYNAMIC_UPDATE_FLAG) != 0;
@@ -48,33 +46,19 @@
         return (flags & FRENCH_LIGATURE_PROCESSING_FLAG) != 0;
     }
 
-    static AK_FORCE_INLINE int getHeaderOptionsPosition(
-            const BinaryDictionaryFormatUtils::FORMAT_VERSION dictionaryFormat) {
-        switch (getHeaderVersion(dictionaryFormat)) {
-        case HEADER_VERSION_2:
-            return VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
-                    + VERSION_2_HEADER_FLAG_SIZE + VERSION_2_HEADER_SIZE_FIELD_SIZE;
-            break;
-        default:
-            return NOT_A_DICT_POS;
-        }
+    static AK_FORCE_INLINE int getHeaderOptionsPosition() {
+        return VERSION_2_HEADER_MAGIC_NUMBER_SIZE + VERSION_2_HEADER_DICTIONARY_VERSION_SIZE
+                + VERSION_2_HEADER_FLAG_SIZE + VERSION_2_HEADER_SIZE_FIELD_SIZE;
     }
 
-    static bool readHeaderValue(
-            const BinaryDictionaryInfo *const binaryDictionaryInfo,
+    static bool readHeaderValue(const uint8_t *const dictBuf,
             const char *const key, int *outValue, const int outValueSize);
 
-    static int readHeaderValueInt(
-            const BinaryDictionaryInfo *const binaryDictionaryInfo, const char *const key);
+    static int readHeaderValueInt(const uint8_t *const dictBuf, const char *const key);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryDictionaryHeaderReadingUtils);
 
-    enum HEADER_VERSION {
-        HEADER_VERSION_2,
-        UNKNOWN_HEADER_VERSION
-    };
-
     static const int VERSION_2_HEADER_MAGIC_NUMBER_SIZE;
     static const int VERSION_2_HEADER_DICTIONARY_VERSION_SIZE;
     static const int VERSION_2_HEADER_FLAG_SIZE;
@@ -88,18 +72,6 @@
     static const DictionaryFlags SUPPORTS_DYNAMIC_UPDATE_FLAG;
     static const DictionaryFlags FRENCH_LIGATURE_PROCESSING_FLAG;
     static const DictionaryFlags CONTAINS_BIGRAMS_FLAG;
-
-    static HEADER_VERSION getHeaderVersion(
-            const BinaryDictionaryFormatUtils::FORMAT_VERSION formatVersion) {
-        switch(formatVersion) {
-            case BinaryDictionaryFormatUtils::VERSION_2:
-                // Fall through
-            case BinaryDictionaryFormatUtils::VERSION_3:
-                return HEADER_VERSION_2;
-            default:
-                return UNKNOWN_HEADER_VERSION;
-        }
-    }
 };
 }
 #endif /* LATINIME_DICTIONARY_HEADER_READING_UTILS_H */
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
index c694c6a..818b2af 100644
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_info.h
@@ -36,7 +36,7 @@
               mDictBufOffset(dictBufOffset), mIsUpdatable(isUpdatable),
               mDictionaryFormat(BinaryDictionaryFormatUtils::detectFormatVersion(
                       mDictBuf, mDictSize)),
-              mDictionaryHeader(this), mDictRoot(mDictBuf + mDictionaryHeader.getSize()),
+              mDictionaryHeader(dictBuf), mDictRoot(mDictBuf + mDictionaryHeader.getSize()),
               // TODO: Remove.
               mStructurePolicy(DictionaryStructureWithBufferPolicyFactory
                       ::newDictionaryStructurePolicy(this)) {
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h
new file mode 100644
index 0000000..558e0a5
--- /dev/null
+++ b/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
+#define LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
+
+#include "defines.h"
+#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
+
+namespace latinime {
+
+class BinaryDictionaryShortcutIterator {
+ public:
+    BinaryDictionaryShortcutIterator(
+            const DictionaryShortcutsStructurePolicy *const shortcutStructurePolicy,
+            const int shortcutPos)
+            : mShortcutStructurePolicy(shortcutStructurePolicy),
+              mPos(shortcutStructurePolicy->getStartPos(shortcutPos)),
+              mHasNextShortcutTarget(shortcutPos != NOT_A_DICT_POS) {}
+
+    AK_FORCE_INLINE bool hasNextShortcutTarget() const {
+        return mHasNextShortcutTarget;
+    }
+
+    // Gets the shortcut target itself as an int string and put it to outTarget, put its length
+    // to outTargetLength, put whether it is whitelist to outIsWhitelist.
+    AK_FORCE_INLINE void nextShortcutTarget(
+            const int maxDepth, int *const outTarget, int *const outTargetLength,
+            bool *const outIsWhitelist) {
+        mShortcutStructurePolicy->getNextShortcut(maxDepth, outTarget, outTargetLength,
+                outIsWhitelist, &mHasNextShortcutTarget, &mPos);
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryDictionaryShortcutIterator);
+
+    const DictionaryShortcutsStructurePolicy *const mShortcutStructurePolicy;
+    int mPos;
+    bool mHasNextShortcutTarget;
+};
+} // namespace latinime
+#endif // LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
diff --git a/native/jni/src/suggest/core/dictionary/shortcut_utils.h b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
index 3c21809..461d7b4 100644
--- a/native/jni/src/suggest/core/dictionary/shortcut_utils.h
+++ b/native/jni/src/suggest/core/dictionary/shortcut_utils.h
@@ -19,21 +19,20 @@
 
 #include "defines.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
-#include "suggest/core/dictionary/terminal_attributes.h"
+#include "suggest/core/dictionary/binary_dictionary_shortcut_iterator.h"
 
 namespace latinime {
 
 class ShortcutUtils {
  public:
-    static int outputShortcuts(const TerminalAttributes *const terminalAttributes,
+    static int outputShortcuts(BinaryDictionaryShortcutIterator *const shortcutIt,
             int outputWordIndex, const int finalScore, int *const outputCodePoints,
             int *const frequencies, int *const outputTypes, const bool sameAsTyped) {
-        TerminalAttributes::ShortcutIterator iterator = terminalAttributes->getShortcutIterator();
         int shortcutTarget[MAX_WORD_LENGTH];
-        while (iterator.hasNextShortcutTarget() && outputWordIndex < MAX_RESULTS) {
+        while (shortcutIt->hasNextShortcutTarget() && outputWordIndex < MAX_RESULTS) {
             bool isWhilelist;
             int shortcutTargetStringLength;
-            iterator.nextShortcutTarget(MAX_WORD_LENGTH, shortcutTarget,
+            shortcutIt->nextShortcutTarget(MAX_WORD_LENGTH, shortcutTarget,
                     &shortcutTargetStringLength, &isWhilelist);
             int shortcutScore;
             int kind;
diff --git a/native/jni/src/suggest/core/dictionary/terminal_attributes.h b/native/jni/src/suggest/core/dictionary/terminal_attributes.h
deleted file mode 100644
index 789450d..0000000
--- a/native/jni/src/suggest/core/dictionary/terminal_attributes.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LATINIME_TERMINAL_ATTRIBUTES_H
-#define LATINIME_TERMINAL_ATTRIBUTES_H
-
-#include <stdint.h>
-
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-
-namespace latinime {
-
-/**
- * This class encapsulates information about a terminal that allows to
- * retrieve local node attributes like the list of shortcuts without
- * exposing the format structure to the client.
- */
-class TerminalAttributes {
- public:
-    class ShortcutIterator {
-     public:
-        ShortcutIterator(const DictionaryShortcutsStructurePolicy *const shortcutStructurePolicy,
-                const int shortcutPos, const bool hasShortcutList)
-                : mShortcutStructurePolicy(shortcutStructurePolicy), mPos(shortcutPos),
-                  mHasNextShortcutTarget(hasShortcutList) {}
-
-        inline bool hasNextShortcutTarget() const {
-            return mHasNextShortcutTarget;
-        }
-
-        // Gets the shortcut target itself as an int string and put it to outTarget, put its length
-        // to outTargetLength, put whether it is whitelist to outIsWhitelist.
-        AK_FORCE_INLINE void nextShortcutTarget(
-                const int maxDepth, int *const outTarget, int *const outTargetLength,
-                bool *const outIsWhitelist) {
-            mShortcutStructurePolicy->getNextShortcut(maxDepth, outTarget, outTargetLength,
-                    outIsWhitelist, &mHasNextShortcutTarget, &mPos);
-        }
-
-     private:
-        const DictionaryShortcutsStructurePolicy *const mShortcutStructurePolicy;
-        int mPos;
-        bool mHasNextShortcutTarget;
-    };
-
-    TerminalAttributes(const DictionaryShortcutsStructurePolicy *const shortcutStructurePolicy,
-            const int shortcutPos)
-            : mShortcutStructurePolicy(shortcutStructurePolicy),
-              mShortcutListSizePos(shortcutPos) {}
-
-    inline ShortcutIterator getShortcutIterator() const {
-        int shortcutPos = mShortcutListSizePos;
-        const bool hasShortcutList = shortcutPos != NOT_A_DICT_POS;
-        if (hasShortcutList) {
-            shortcutPos = mShortcutStructurePolicy->getStartPos(shortcutPos);
-        }
-        // shortcutPos is never used if hasShortcutList is false.
-        return ShortcutIterator(mShortcutStructurePolicy, shortcutPos, hasShortcutList);
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(TerminalAttributes);
-    const DictionaryShortcutsStructurePolicy *const mShortcutStructurePolicy;
-    const int mShortcutListSizePos;
-};
-} // namespace latinime
-#endif // LATINIME_TERMINAL_ATTRIBUTES_H
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index e2b96ad..bc1f25d 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -21,10 +21,10 @@
 #include "suggest/core/dicnode/dic_node_vector.h"
 // TODO: Use DictionaryStructurePolicy instead of BinaryDictionaryInfo.
 #include "suggest/core/dictionary/binary_dictionary_info.h"
+#include "suggest/core/dictionary/binary_dictionary_shortcut_iterator.h"
 #include "suggest/core/dictionary/dictionary.h"
 #include "suggest/core/dictionary/digraph_utils.h"
 #include "suggest/core/dictionary/shortcut_utils.h"
-#include "suggest/core/dictionary/terminal_attributes.h"
 #include "suggest/core/layout/proximity_info.h"
 #include "suggest/core/policy/scoring.h"
 #include "suggest/core/policy/traversal.h"
@@ -214,13 +214,13 @@
         if (!terminalDicNode->hasMultipleWords()) {
             const DictionaryStructureWithBufferPolicy *const structurePolicy =
                     traverseSession->getBinaryDictionaryInfo()->getStructurePolicy();
-            const TerminalAttributes terminalAttributes(
+            BinaryDictionaryShortcutIterator shortcutIt(
                     structurePolicy->getShortcutsStructurePolicy(),
                     structurePolicy->getShortcutPositionOfNode(terminalDicNode->getPos()));
             // Shortcut is not supported for multiple words suggestions.
             // TODO: Check shortcuts during traversal for multiple words suggestions.
             const bool sameAsTyped = TRAVERSAL->sameAsTyped(traverseSession, terminalDicNode);
-            outputWordIndex = ShortcutUtils::outputShortcuts(&terminalAttributes, outputWordIndex,
+            outputWordIndex = ShortcutUtils::outputShortcuts(&shortcutIt, outputWordIndex,
                     finalScore, outputCodePoints, frequencies, outputTypes, sameAsTyped);
         }
         DicNode::managedDelete(terminalDicNode);
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h
index 0b112a5..3c7fab0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_policy.h
@@ -34,33 +34,29 @@
 
     int getStartPos(const int pos) const {
         int listPos = pos;
-        BinaryDictionaryTerminalAttributesReadingUtils::getShortcutListSizeAndForwardPointer(
-                mShortcutsBuf, &listPos);
+        ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(mShortcutsBuf, &listPos);
         return listPos;
     }
 
     void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
             int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
             int *const pos) const {
-        const BinaryDictionaryTerminalAttributesReadingUtils::ShortcutFlags flags =
-                BinaryDictionaryTerminalAttributesReadingUtils::getFlagsAndForwardPointer(
-                        mShortcutsBuf, pos);
+        const ShortcutListReadingUtils::ShortcutFlags flags =
+                ShortcutListReadingUtils::getFlagsAndForwardPointer(mShortcutsBuf, pos);
         if (outHasNext) {
-            *outHasNext = BinaryDictionaryTerminalAttributesReadingUtils::hasNext(flags);
+            *outHasNext = ShortcutListReadingUtils::hasNext(flags);
         }
         if (outIsWhitelist) {
-            *outIsWhitelist =
-                    BinaryDictionaryTerminalAttributesReadingUtils::isWhitelist(flags);
+            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(flags);
         }
         if (outCodePoint) {
-            *outCodePointCount =
-                    BinaryDictionaryTerminalAttributesReadingUtils::readShortcutTarget(
-                            mShortcutsBuf, maxCodePointCount, outCodePoint, pos);
+            *outCodePointCount = ShortcutListReadingUtils::readShortcutTarget(
+                        mShortcutsBuf, maxCodePointCount, outCodePoint, pos);
         }
     }
 
     void skipAllShortcuts(int *const pos) const {
-        const int shortcutListSize = BinaryDictionaryTerminalAttributesReadingUtils
+        const int shortcutListSize = ShortcutListReadingUtils
                 ::getShortcutListSizeAndForwardPointer(mShortcutsBuf, pos);
         *pos += shortcutListSize;
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp
index 61c3a13..e70bb50 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.cpp
@@ -16,24 +16,16 @@
 
 #include "suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h"
 
-#include "suggest/core/dictionary/byte_array_utils.h"
-
 namespace latinime {
 
-typedef BinaryDictionaryTerminalAttributesReadingUtils TaUtils;
-
-const TaUtils::TerminalAttributeFlags TaUtils::MASK_ATTRIBUTE_ADDRESS_TYPE = 0x30;
-const TaUtils::TerminalAttributeFlags TaUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
-const TaUtils::TerminalAttributeFlags TaUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
-const TaUtils::TerminalAttributeFlags TaUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
-const TaUtils::TerminalAttributeFlags TaUtils::FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40;
 // Flag for presence of more attributes
-const TaUtils::TerminalAttributeFlags TaUtils::FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
+const ShortcutListReadingUtils::ShortcutFlags
+        ShortcutListReadingUtils::FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
 // Mask for attribute probability, stored on 4 bits inside the flags byte.
-const TaUtils::TerminalAttributeFlags TaUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
-const int TaUtils::ATTRIBUTE_ADDRESS_SHIFT = 4;
-const int TaUtils::SHORTCUT_LIST_SIZE_FIELD_SIZE = 2;
+const ShortcutListReadingUtils::ShortcutFlags
+        ShortcutListReadingUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
+const int ShortcutListReadingUtils::SHORTCUT_LIST_SIZE_FIELD_SIZE = 2;
 // The numeric value of the shortcut probability that means 'whitelist'.
-const int TaUtils::WHITELIST_SHORTCUT_PROBABILITY = 15;
+const int ShortcutListReadingUtils::WHITELIST_SHORTCUT_PROBABILITY = 15;
 
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h
index 3799d84..e92fa5f 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/shortcut/shortcut_list_reading_utils.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef LATINIME_BINARY_DICTIONARY_TERMINAL_ATTRIBUTES_READING_UTILS_H
-#define LATINIME_BINARY_DICTIONARY_TERMINAL_ATTRIBUTES_READING_UTILS_H
+#ifndef LATINIME_SHORTCUT_LIST_READING_UTILS_H
+#define LATINIME_SHORTCUT_LIST_READING_UTILS_H
 
 #include <stdint.h>
 
@@ -24,25 +24,23 @@
 
 namespace latinime {
 
-class BinaryDictionaryTerminalAttributesReadingUtils {
+class ShortcutListReadingUtils {
  public:
-    typedef uint8_t TerminalAttributeFlags;
-    typedef TerminalAttributeFlags ShortcutFlags;
+    typedef uint8_t ShortcutFlags;
 
-    static AK_FORCE_INLINE TerminalAttributeFlags getFlagsAndForwardPointer(
+    static AK_FORCE_INLINE ShortcutFlags getFlagsAndForwardPointer(
             const uint8_t *const dictRoot, int *const pos) {
         return ByteArrayUtils::readUint8AndAdvancePosition(dictRoot, pos);
     }
 
-    static AK_FORCE_INLINE int getProbabilityFromFlags(const TerminalAttributeFlags flags) {
+    static AK_FORCE_INLINE int getProbabilityFromFlags(const ShortcutFlags flags) {
         return flags & MASK_ATTRIBUTE_PROBABILITY;
     }
 
-    static AK_FORCE_INLINE bool hasNext(const TerminalAttributeFlags flags) {
+    static AK_FORCE_INLINE bool hasNext(const ShortcutFlags flags) {
         return (flags & FLAG_ATTRIBUTE_HAS_NEXT) != 0;
     }
 
-    // Shortcuts reading methods
     // This method returns the size of the shortcut list region excluding the shortcut list size
     // field at the beginning.
     static AK_FORCE_INLINE int getShortcutListSizeAndForwardPointer(
@@ -68,35 +66,12 @@
     }
 
  private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryDictionaryTerminalAttributesReadingUtils);
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutListReadingUtils);
 
-    static const TerminalAttributeFlags MASK_ATTRIBUTE_ADDRESS_TYPE;
-    static const TerminalAttributeFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE;
-    static const TerminalAttributeFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES;
-    static const TerminalAttributeFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES;
-    static const TerminalAttributeFlags FLAG_ATTRIBUTE_OFFSET_NEGATIVE;
-    static const TerminalAttributeFlags FLAG_ATTRIBUTE_HAS_NEXT;
-    static const TerminalAttributeFlags MASK_ATTRIBUTE_PROBABILITY;
-    static const int ATTRIBUTE_ADDRESS_SHIFT;
+    static const ShortcutFlags FLAG_ATTRIBUTE_HAS_NEXT;
+    static const ShortcutFlags MASK_ATTRIBUTE_PROBABILITY;
     static const int SHORTCUT_LIST_SIZE_FIELD_SIZE;
     static const int WHITELIST_SHORTCUT_PROBABILITY;
-
-    static AK_FORCE_INLINE bool isOffsetNegative(const TerminalAttributeFlags flags) {
-        return (flags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) != 0;
-    }
-
-    static AK_FORCE_INLINE int attributeAddressSize(const TerminalAttributeFlags flags) {
-        return (flags & MASK_ATTRIBUTE_ADDRESS_TYPE) >> ATTRIBUTE_ADDRESS_SHIFT;
-        /* Note: this is a value-dependant optimization of what may probably be
-           more readably written this way:
-           switch (flags * BinaryFormat::MASK_ATTRIBUTE_ADDRESS_TYPE) {
-           case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE: return 1;
-           case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES: return 2;
-           case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTE: return 3;
-           default: return 0;
-           }
-        */
-    }
 };
-}
-#endif /* LATINIME_BINARY_DICTIONARY_TERMINAL_ATTRIBUTES_READING_UTILS_H */
+} // namespace latinime
+#endif // LATINIME_SHORTCUT_LIST_READING_UTILS_H
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index eb4f706..ead134b 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -204,17 +204,16 @@
         // view and only delegates to the parts of the code that care. So we don't include them here
         // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies,
         // but keep them in mind if something breaks. Commenting them out as is should work.
-        //mLatinIME.onPressKey(codePoint);
-        for (final Key key : mKeyboard.mKeys) {
-            if (key.mCode == codePoint) {
-                final int x = key.mX + key.mWidth / 2;
-                final int y = key.mY + key.mHeight / 2;
-                mLatinIME.onCodeInput(codePoint, x, y);
-                return;
-            }
+        //mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
+        final Key key = mKeyboard.getKey(codePoint);
+        if (key != null) {
+            final int x = key.mX + key.mWidth / 2;
+            final int y = key.mY + key.mHeight / 2;
+            mLatinIME.onCodeInput(codePoint, x, y);
+            return;
         }
         mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
-        //mLatinIME.onReleaseKey(codePoint, false);
+        //mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
     }
 
     protected void type(final String stringToType) {
diff --git a/tools/maketext/res/values-ar/donottranslate-more-keys.xml b/tools/maketext/res/values-ar/donottranslate-more-keys.xml
index cace240..8b86b1b 100644
--- a/tools/maketext/res/values-ar/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-ar/donottranslate-more-keys.xml
@@ -81,7 +81,7 @@
     <!-- U+061F: "؟" ARABIC QUESTION MARK
          U+060C: "،" ARABIC COMMA
          U+061B: "؛" ARABIC SEMICOLON -->
-    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,&#x060C;,&#x061F;,\@,&amp;,\\%,+,&#x061B;,/,(,)"</string>
+    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,&#x060C;,&#x061F;,\@,&amp;,\\%,+,&#x061B;,/,(|),)|("</string>
     <string name="more_keys_for_apostrophe">"&#x061F;,&#x061B;,!,:,-,/,\',\""</string>
     <!-- U+266A: "♪" EIGHTH NOTE -->
     <string name="more_keys_for_bullet">&#x266A;</string>
diff --git a/tools/maketext/res/values-fa/donottranslate-more-keys.xml b/tools/maketext/res/values-fa/donottranslate-more-keys.xml
index 7c8496d..6d13d6b 100644
--- a/tools/maketext/res/values-fa/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-fa/donottranslate-more-keys.xml
@@ -89,7 +89,7 @@
     <!-- U+061F: "؟" ARABIC QUESTION MARK
          U+060C: "،" ARABIC COMMA
          U+061B: "؛" ARABIC SEMICOLON -->
-    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,&#x060C;,&#x061F;,\@,&amp;,\\%,+,&#x061B;,/,(,)"</string>
+    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,&#x060C;,&#x061F;,\@,&amp;,\\%,+,&#x061B;,/,(|),)|("</string>
     <!-- U+266A: "♪" EIGHTH NOTE -->
     <string name="more_keys_for_bullet">&#x266A;</string>
     <!-- U+2605: "★" BLACK STAR
diff --git a/tools/maketext/res/values-iw/donottranslate-more-keys.xml b/tools/maketext/res/values-iw/donottranslate-more-keys.xml
index 64d4227..9d2e01e 100644
--- a/tools/maketext/res/values-iw/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-iw/donottranslate-more-keys.xml
@@ -23,6 +23,7 @@
          U+05D1: "ב" HEBREW LETTER BET
          U+05D2: "ג" HEBREW LETTER GIMEL -->
     <string name="label_to_alpha_key">&#x05D0;&#x05D1;&#x05D2;</string>
+    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,\\,,\?,\@,&amp;,\\%,+,;,/,(|),)|("</string>
     <!-- U+2605: "★" BLACK STAR -->
     <string name="more_keys_for_star">&#x2605;</string>
     <!-- U+00B1: "±" PLUS-MINUS SIGN