Merge "Fix emoji tabs"
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
index 5674cb4..14682e3 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.cpp
@@ -28,6 +28,7 @@
     const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(nodePos);
     const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
     int pos = nodePos;
+    mHeadPos = nodePos;
     if (usesAdditionalBuffer) {
         pos -= mBuffer->getOriginalBufferSize();
     }
@@ -57,7 +58,7 @@
         mChildrenPosFieldPos += mBuffer->getOriginalBufferSize();
     }
     mChildrenPos = DynamicPatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
-            dictBuf, mFlags, &pos);
+            dictBuf, &pos);
     if (usesAdditionalBuffer && mChildrenPos != NOT_A_DICT_POS) {
         mChildrenPos += mBuffer->getOriginalBufferSize();
     }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h
index 2ee7c24..30d251f 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_node_reader.h
@@ -39,8 +39,8 @@
             const DictionaryBigramsStructurePolicy *const bigramsPolicy,
             const DictionaryShortcutsStructurePolicy *const shortcutsPolicy)
             : mBuffer(buffer), mBigramsPolicy(bigramsPolicy),
-              mShortcutsPolicy(shortcutsPolicy), mNodePos(NOT_A_VALID_WORD_POS), mFlags(0),
-              mParentPos(NOT_A_DICT_POS),  mCodePointCount(0),
+              mShortcutsPolicy(shortcutsPolicy), mNodePos(NOT_A_VALID_WORD_POS),
+              mHeadPos(NOT_A_DICT_POS), mFlags(0), mParentPos(NOT_A_DICT_POS), mCodePointCount(0),
               mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY),
               mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
               mShortcutPos(NOT_A_DICT_POS), mBigramPos(NOT_A_DICT_POS),
@@ -65,6 +65,11 @@
         return mNodePos;
     }
 
+    // HeadPos is different from NodePos when the current PtNode is a moved PtNode.
+    AK_FORCE_INLINE int getHeadPos() const {
+        return mHeadPos;
+    }
+
     // Flags
     AK_FORCE_INLINE bool isDeleted() const {
         return DynamicPatriciaTrieReadingUtils::isDeleted(mFlags);
@@ -136,6 +141,7 @@
     const DictionaryBigramsStructurePolicy *const mBigramsPolicy;
     const DictionaryShortcutsStructurePolicy *const mShortcutsPolicy;
     int mNodePos;
+    int mHeadPos;
     DynamicPatriciaTrieReadingUtils::NodeFlags mFlags;
     int mParentPos;
     uint8_t mCodePointCount;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp
index 5d979fa..c7e89ff 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.cpp
@@ -29,18 +29,14 @@
 const DptReadingUtils::NodeFlags DptReadingUtils::FLAG_IS_DELETED = 0x80;
 
 /* static */ int DptReadingUtils::readChildrenPositionAndAdvancePosition(
-        const uint8_t *const buffer, const NodeFlags flags, int *const pos) {
-    if ((flags & MASK_MOVED) == FLAG_IS_NOT_MOVED) {
-        const int base = *pos;
-        const int offset = ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
-        if (offset == 0) {
-            // 0 offset means that the node does not have children.
-            return NOT_A_DICT_POS;
-        } else {
-            return base + offset;
-        }
-    } else {
+        const uint8_t *const buffer, int *const pos) {
+    const int base = *pos;
+    const int offset = ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
+    if (offset == 0) {
+        // 0 offset means that the node does not have children.
         return NOT_A_DICT_POS;
+    } else {
+        return base + offset;
     }
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
index 2e604a2..5a2ad9c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_reading_utils.h
@@ -42,8 +42,7 @@
         return ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
     }
 
-    static int readChildrenPositionAndAdvancePosition(const uint8_t *const buffer,
-            const NodeFlags flags, int *const pos);
+    static int readChildrenPositionAndAdvancePosition(const uint8_t *const buffer, int *const pos);
 
     /**
      * Node Flags
diff --git a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp
index 7c0b628..7dfa9ec 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/dynamic_patricia_trie_writing_helper.cpp
@@ -125,6 +125,24 @@
             mBuffer, movedPosOffset, &writingPos)) {
         return false;
     }
+    if (originalNode->hasChildren()) {
+        // Update children's parent position.
+        DynamicPatriciaTrieReadingHelper readingHelper(mBuffer, mBigramPolicy, mShortcutPolicy);
+        const DynamicPatriciaTrieNodeReader *const nodeReader = readingHelper.getNodeReader();
+        readingHelper.initWithNodeArrayPos(originalNode->getChildrenPos());
+        while (!readingHelper.isEnd()) {
+            const int childPtNodeWrittenPos = nodeReader->getHeadPos();
+            const int parentOffset = movedPos - childPtNodeWrittenPos;
+            int parentOffsetFieldPos = childPtNodeWrittenPos + 1 /* Flags */;
+            if (!DynamicPatriciaTrieWritingUtils::writeParentOffsetAndAdvancePosition(
+                    mBuffer, parentOffset, &parentOffsetFieldPos)) {
+                // Parent offset cannot be written because of a bug or a broken dictionary; thus,
+                // we give up to update dictionary.
+                return false;
+            }
+            readingHelper.readNextSiblingNode();
+        }
+    }
     return true;
 }
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
index f727ecf..6bafb64 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
@@ -172,6 +172,7 @@
         int codePoint = readCodePointAndAdvancePosition(buffer, pos);
         while (NOT_A_CODE_POINT != codePoint && length < maxLength) {
             codePoint = readCodePointAndAdvancePosition(buffer, pos);
+            length++;
         }
         return length;
     }