Reconcile with jb-mr1-factory-release jb-mr1-release - do not merge

Change-Id: I4a04730079d76f1d050c1bcdeb701bd8bbb79511
diff --git a/dictionaries/en_gb_wordlist.xml.gz b/dictionaries/en_gb_wordlist.xml.gz
index 927f2d1..274424c 100644
--- a/dictionaries/en_gb_wordlist.xml.gz
+++ b/dictionaries/en_gb_wordlist.xml.gz
Binary files differ
diff --git a/dictionaries/en_us_wordlist.xml.gz b/dictionaries/en_us_wordlist.xml.gz
index 4cad38b..b5054ef 100644
--- a/dictionaries/en_us_wordlist.xml.gz
+++ b/dictionaries/en_us_wordlist.xml.gz
Binary files differ
diff --git a/dictionaries/en_whitelist.xml.gz b/dictionaries/en_whitelist.xml.gz
index 844e020..cf70a1a 100644
--- a/dictionaries/en_whitelist.xml.gz
+++ b/dictionaries/en_whitelist.xml.gz
Binary files differ
diff --git a/dictionaries/en_wordlist.xml.gz b/dictionaries/en_wordlist.xml.gz
index 01dcc28..6e57f42 100644
--- a/dictionaries/en_wordlist.xml.gz
+++ b/dictionaries/en_wordlist.xml.gz
Binary files differ
diff --git a/dictionaries/fr_wordlist.xml.gz b/dictionaries/fr_wordlist.xml.gz
index 50f4604..3134a04 100644
--- a/dictionaries/fr_wordlist.xml.gz
+++ b/dictionaries/fr_wordlist.xml.gz
Binary files differ
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index bd7737a..de1170a 100644
--- a/java/res/raw/main_en.dict
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 2fd94f4..c607d0e 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 5eb0f08..4388a27 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -24,7 +24,7 @@
     <string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string>
     <string name="english_ime_research_log" msgid="8492602295696577851">"Amri za Kumbukumbu za Utafiti"</string>
     <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string>
-    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya wasiliani"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya unaowasiliana nao"</string>
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e99e956..38025e8 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -389,7 +389,7 @@
         }
     }
 
-    public int getManualCapsMode() {
+    public int getKeyboardShiftMode() {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
             return WordComposer.CAPS_MODE_OFF;
@@ -400,6 +400,8 @@
             return WordComposer.CAPS_MODE_MANUAL_SHIFT_LOCKED;
         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
             return WordComposer.CAPS_MODE_MANUAL_SHIFTED;
+        case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
+            return WordComposer.CAPS_MODE_AUTO_SHIFTED;
         default:
             return WordComposer.CAPS_MODE_OFF;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index b39f2ba..472f74b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -105,7 +105,7 @@
     private static final String TAG = KeyboardView.class.getSimpleName();
 
     // XML attributes
-    private final KeyVisualAttributes mKeyVisualAttributes;
+    protected final KeyVisualAttributes mKeyVisualAttributes;
     private final int mKeyLabelHorizontalPadding;
     private final float mKeyHintLetterPadding;
     private final float mKeyPopupHintLetterPadding;
@@ -733,6 +733,7 @@
         return width;
     }
 
+    // TODO: Remove this method.
     public float getLabelWidth(final String label, final Paint paint) {
         paint.getTextBounds(label, 0, label.length(), mTextBounds);
         return mTextBounds.width();
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index ccf6932..d0f7cb2 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -180,8 +180,9 @@
 
     static final class BogusMoveEventDetector {
         // Move these thresholds to resource.
-        private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.70f; // in keyWidth
-        private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.50f; // in keyWidth
+        // These thresholds' unit is a diagonal length of a key.
+        private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.53f;
+        private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.14f;
 
         private int mAccumulatedDistanceThreshold;
         private int mRadiusThreshold;
@@ -191,10 +192,11 @@
         private int mActualDownX;
         private int mActualDownY;
 
-        public void setKeyboardGeometry(final int keyWidth) {
+        public void setKeyboardGeometry(final int keyWidth, final int keyHeight) {
+            final float keyDiagonal = (float)Math.hypot(keyWidth, keyHeight);
             mAccumulatedDistanceThreshold = (int)(
-                    keyWidth * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD);
-            mRadiusThreshold = (int)(keyWidth * BOGUS_MOVE_RADIUS_THRESHOLD);
+                    keyDiagonal * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD);
+            mRadiusThreshold = (int)(keyDiagonal * BOGUS_MOVE_RADIUS_THRESHOLD);
         }
 
         public void onActualDownEvent(final int x, final int y) {
@@ -210,8 +212,12 @@
             mAccumulatedDistanceFromDownKey += distance;
         }
 
-        public boolean hasTraveledLongDistance() {
-            return mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold;
+        public boolean hasTraveledLongDistance(final int x, final int y) {
+            final int dx = Math.abs(x - mActualDownX);
+            final int dy = Math.abs(y - mActualDownY);
+            // A bogus move event should be a horizontal movement. A vertical movement might be
+            // a sloppy typing and should be ignored.
+            return dx >= dy && mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold;
         }
 
         /* package */ int getDistanceFromDownEvent(final int x, final int y) {
@@ -514,7 +520,9 @@
         }
         mKeyDetector = keyDetector;
         mKeyboard = keyDetector.getKeyboard();
-        mGestureStrokeWithPreviewPoints.setKeyboardGeometry(mKeyboard.mMostCommonKeyWidth);
+        final int keyWidth = mKeyboard.mMostCommonKeyWidth;
+        final int keyHeight = mKeyboard.mMostCommonKeyHeight;
+        mGestureStrokeWithPreviewPoints.setKeyboardGeometry(keyWidth);
         final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
         if (newKey != mCurrentKey) {
             if (mDrawingProxy != null) {
@@ -522,9 +530,8 @@
             }
             // Keep {@link #mCurrentKey} that comes from previous keyboard.
         }
-        final int keyWidth = mKeyboard.mMostCommonKeyWidth;
         mPhantonSuddenMoveThreshold = (int)(keyWidth * PHANTOM_SUDDEN_MOVE_THRESHOLD);
-        mBogusMoveEventDetector.setKeyboardGeometry(keyWidth);
+        mBogusMoveEventDetector.setKeyboardGeometry(keyWidth, keyHeight);
     }
 
     @Override
@@ -962,11 +969,13 @@
                             && sTimeRecorder.isInFastTyping(eventTime)
                             && mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) {
                         if (DEBUG_MODE) {
+                            final float keyDiagonal = (float)Math.hypot(
+                                    mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight);
                             final float radiusRatio =
-                                    (float)mBogusMoveEventDetector.getDistanceFromDownEvent(x, y)
-                                    / mKeyboard.mMostCommonKeyWidth;
+                                    mBogusMoveEventDetector.getDistanceFromDownEvent(x, y)
+                                    / keyDiagonal;
                             Log.w(TAG, String.format("[%d] onMoveEvent:"
-                                    + " bogus down-move-up event (raidus=%.2f keyWidth) is "
+                                    + " bogus down-move-up event (raidus=%.2f key diagonal) is "
                                     + " translated to up[%d,%d,%s]/down[%d,%d,%s] events",
                                     mPointerId, radiusRatio,
                                     lastX, lastY, Keyboard.printableCode(oldKey.mCode),
@@ -1146,24 +1155,24 @@
             final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y);
             if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) {
                 if (DEBUG_MODE) {
-                    final int keyWidth = mKeyboard.mMostCommonKeyWidth;
-                    final float distanceToEdgeRatio = (float)distanceFromKeyEdgeSquared
-                            / (keyWidth * keyWidth);
+                    final float distanceToEdgeRatio = (float)Math.sqrt(distanceFromKeyEdgeSquared)
+                            / mKeyboard.mMostCommonKeyWidth;
                     Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
-                            +" %.2f keyWidth from key edge",
+                            +" %.2f key width from key edge",
                             mPointerId, distanceToEdgeRatio));
                 }
                 return true;
             }
             if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput
                     && sTimeRecorder.isInFastTyping(eventTime)
-                    && mBogusMoveEventDetector.hasTraveledLongDistance()) {
+                    && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) {
                 if (DEBUG_MODE) {
+                    final float keyDiagonal = (float)Math.hypot(
+                            mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight);
                     final float lengthFromDownRatio =
-                            (float)mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey
-                            / mKeyboard.mMostCommonKeyWidth;
+                            mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey / keyDiagonal;
                     Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
-                            + " %.2f keyWidth from virtual down point",
+                            + " %.2f key diagonal from virtual down point",
                             mPointerId, lengthFromDownRatio));
                 }
                 return true;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index 3b7c6ad..3bb272f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -799,8 +799,12 @@
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
         /* 0 */ "\u00E4,\u00E2,\u00E0,\u00E1,\u00E6,\u00E3,\u00E5,\u0101",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        /* 1 */ "\u0117",
+        /* 1 */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0117",
         /* 2 */ null,
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d98966e..8ac0cd4 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1063,7 +1063,16 @@
         // Reread resource value here, because this method is called by framework anytime as needed.
         final boolean isFullscreenModeAllowed =
                 mCurrentSettings.isFullscreenModeAllowed(getResources());
-        return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed;
+        if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
+            // TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI
+            // implies NO_FULLSCREEN. However, the framework mistakenly does.  i.e. NO_EXTRACT_UI
+            // without NO_FULLSCREEN doesn't work as expected. Because of this we need this
+            // hack for now.  Let's get rid of this once the framework gets fixed.
+            final EditorInfo ei = getCurrentInputEditorInfo();
+            return !(ei != null && ((ei.imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0));
+        } else {
+            return false;
+        }
     }
 
     @Override
@@ -1119,8 +1128,8 @@
 
     // Factor in auto-caps and manual caps and compute the current caps mode.
     private int getActualCapsMode() {
-        final int manual = mKeyboardSwitcher.getManualCapsMode();
-        if (manual != WordComposer.CAPS_MODE_OFF) return manual;
+        final int keyboardShiftMode = mKeyboardSwitcher.getKeyboardShiftMode();
+        if (keyboardShiftMode != WordComposer.CAPS_MODE_AUTO_SHIFTED) return keyboardShiftMode;
         final int auto = getCurrentAutoCapsState();
         if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) {
             return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED;
@@ -1429,6 +1438,16 @@
             // The following is necessary for the case where the user typed something but didn't
             // manual pick it and didn't input any separator.
             mSpaceState = SPACE_STATE_PHANTOM;
+        } else {
+            final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+            // TODO: reverse this logic. We should have the means to determine whether a character
+            // should usually be followed by a space, and it should be more readable.
+            if (Constants.NOT_A_CODE != codePointBeforeCursor
+                    && !Character.isWhitespace(codePointBeforeCursor)
+                    && !mCurrentSettings.isPhantomSpacePromotingSymbol(codePointBeforeCursor)
+                    && !mCurrentSettings.isWeakSpaceStripper(codePointBeforeCursor)) {
+                mSpaceState = SPACE_STATE_PHANTOM;
+            }
         }
         mConnection.endBatchEdit();
         mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode());
@@ -1564,6 +1583,7 @@
         // We have a TLD (or something that looks like this): make sure we don't add
         // a space even if currently in phantom mode.
         mSpaceState = SPACE_STATE_NONE;
+        // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code
         final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0);
         if (lastOne != null && lastOne.length() == 1
                 && lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
@@ -2284,6 +2304,7 @@
             // This is a stopgap solution to avoid leaving a high surrogate alone in a text view.
             // In the future, we need to deprecate deteleSurroundingText() and have a surrogate
             // pair-friendly way of deleting characters in InputConnection.
+            // TODO: use getCodePointBeforeCursor instead to improve performance
             final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0);
             if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
                 mConnection.deleteSurroundingText(1, 0);
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index b27db57..2144136 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -235,7 +235,14 @@
                 hasSpaceBefore);
     }
 
+    public int getCodePointBeforeCursor() {
+        if (mCommittedTextBeforeComposingText.length() < 1) return Constants.NOT_A_CODE;
+        return Character.codePointBefore(mCommittedTextBeforeComposingText,
+                mCommittedTextBeforeComposingText.length());
+    }
+
     public CharSequence getTextBeforeCursor(final int i, final int j) {
+        // TODO: use mCommittedTextBeforeComposingText if possible to improve performance
         mIC = mParent.getCurrentInputConnection();
         if (null != mIC) return mIC.getTextBeforeCursor(i, j);
         return null;
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 1c5864b..2a778aa 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -254,11 +254,13 @@
         return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
     }
 
+    // TODO: use "Phantom" instead of "Weak" in this method name
     public boolean isWeakSpaceStripper(final int code) {
         // TODO: this does not work if the code does not fit in a char
         return mWeakSpaceStrippers.contains(String.valueOf((char)code));
     }
 
+    // TODO: use "Phantom" instead of "Weak" in this method name
     public boolean isWeakSpaceSwapper(final int code) {
         // TODO: this does not work if the code does not fit in a char
         return mWeakSpaceSwappers.contains(String.valueOf((char)code));
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index e9bf0fa..4e9fd19 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -51,10 +51,11 @@
             super();
         }
 
+        // TODO: Remove {@link MoreSuggestionsView} argument.
         public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth,
                 final int minWidth, final int maxRow, final MoreSuggestionsView view) {
             clearKeys();
-            final Resources res = view.getContext().getResources();
+            final Resources res = view.getResources();
             mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
             mDividerWidth = mDivider.getIntrinsicWidth();
             final int padding = (int) res.getDimension(
@@ -181,6 +182,7 @@
             load(xmlId, keyboard.mId);
             mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2;
 
+            mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
             final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
                     mPaneView);
             mFromPos = fromPos;
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 9b9a354..03a2e73 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -105,6 +105,10 @@
         }
     }
 
+    public void updateKeyboardGeometry(final int keyHeight) {
+        mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
+    }
+
     @Override
     public void setKeyboard(Keyboard keyboard) {
         super.setKeyboard(keyboard);
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index 49d044f..e3649bd 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -798,7 +798,8 @@
             // into inputIndex if there is a match.
             const bool isAlike = testCharGroupForContinuedLikeness(flags, root, pos, inWord,
                     inputIndex, inputSize, newWord, &inputIndex, &pos);
-            if (isAlike && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) {
+            if (isAlike && (!(BinaryFormat::FLAG_IS_NOT_A_WORD & flags))
+                    && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) {
                 const int frequency = BinaryFormat::readFrequencyWithoutMovingPointer(root, pos);
                 onTerminalWordLike(frequency, newWord, inputIndex, outWord, &maxFreq);
             }
diff --git a/tools/maketext/res/values-de/donottranslate-more-keys.xml b/tools/maketext/res/values-de/donottranslate-more-keys.xml
index 562e574..181a3b5 100644
--- a/tools/maketext/res/values-de/donottranslate-more-keys.xml
+++ b/tools/maketext/res/values-de/donottranslate-more-keys.xml
@@ -27,8 +27,12 @@
          U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
     <string name="more_keys_for_a">&#x00E4;,&#x00E2;,&#x00E0;,&#x00E1;,&#x00E6;,&#x00E3;,&#x00E5;,&#x0101;</string>
-    <!-- U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE -->
-    <string name="more_keys_for_e">&#x0117;</string>
+    <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+         U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+         U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+         U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+         U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE -->
+    <string name="more_keys_for_e">&#x00E9;,&#x00E8;,&#x00EA;,&#x00EB;,&#x0117;</string>
     <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
          U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
          U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE