Merge "Import revised translations."
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 223fcfb..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index c9d3d74..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 5ed614a..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 00168b2..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 980547e..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 868eec3..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 27d2b7d..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index d89bdda..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index e11d854..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index 0eb4aa2..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index b53456a..0000000
--- a/java/res/drawable-sw600dp-hdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index 66111ee..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index 5420161..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 1821337..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 3c81666..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index 6e3d718..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index ea2f0e9..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 9c08b5a..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index dac90bb..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 79f3735..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index b1678f0..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 58142fa..0000000
--- a/java/res/drawable-sw600dp-mdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png
deleted file mode 100644
index df64bbe..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_delete_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
deleted file mode 100644
index 13f78c4..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_return_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png
deleted file mode 100644
index 7e0f1ae..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_search_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png
deleted file mode 100644
index 8c1395e..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_settings_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png
deleted file mode 100644
index a4068ea..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png
deleted file mode 100644
index 4cb37cd..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_shift_locked_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png
deleted file mode 100644
index 481d889..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_smiley_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png
deleted file mode 100644
index 4bfbf66..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_space_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png
deleted file mode 100644
index 1ea57c5..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_tab_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png
deleted file mode 100644
index 597be7d..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png b/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png
deleted file mode 100644
index 58fd48b..0000000
--- a/java/res/drawable-sw600dp-xhdpi/sym_keyboard_voice_off_holo.png
+++ /dev/null
Binary files differ
diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml
index c75fcc0..1d26338 100644
--- a/java/res/values-sw600dp-land/dimens.xml
+++ b/java/res/values-sw600dp-land/dimens.xml
@@ -44,7 +44,7 @@
     <dimen name="key_label_horizontal_padding">18dip</dimen>
 
     <fraction name="key_letter_ratio">45%</fraction>
-    <fraction name="key_large_letter_ratio">45%</fraction>
+    <fraction name="key_large_letter_ratio">48%</fraction>
     <fraction name="key_label_ratio">32%</fraction>
     <fraction name="key_hint_letter_ratio">23%</fraction>
     <fraction name="key_hint_label_ratio">34%</fraction>
diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index 20876a2..942bc72 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -53,12 +53,12 @@
     <dimen name="key_hint_letter_padding">3dp</dimen>
     <dimen name="key_uppercase_letter_padding">3dp</dimen>
 
-    <fraction name="key_letter_ratio">37%</fraction>
-    <fraction name="key_large_letter_ratio">37%</fraction>
-    <fraction name="key_label_ratio">22%</fraction>
+    <fraction name="key_letter_ratio">42%</fraction>
+    <fraction name="key_large_letter_ratio">45%</fraction>
+    <fraction name="key_label_ratio">25%</fraction>
     <fraction name="key_hint_letter_ratio">23%</fraction>
-    <fraction name="key_hint_label_ratio">26%</fraction>
-    <fraction name="key_uppercase_letter_ratio">25%</fraction>
+    <fraction name="key_hint_label_ratio">28%</fraction>
+    <fraction name="key_uppercase_letter_ratio">26%</fraction>
     <fraction name="key_preview_text_ratio">50%</fraction>
     <dimen name="key_preview_height">15.0mm</dimen>
     <dimen name="key_preview_offset">0.1in</dimen>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 172ca2f..4cabe93 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -107,10 +107,11 @@
     </declare-styleable>
 
     <declare-styleable name="CandidateView">
-        <attr name="autoCorrectHighlight" format="integer">
+        <attr name="suggestionStripOption" format="integer">
             <flag name="autoCorrectBold" value="0x01" />
             <flag name="autoCorrectUnderline" value="0x02" />
             <flag name="autoCorrectInvert" value="0x04" />
+            <flag name="validTypedWordBold" value="0x08" />
         </attr>
         <attr name="colorTypedWord" format="color" />
         <attr name="colorAutoCorrect" format="color" />
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 8145d05..cb9edb0 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -85,7 +85,7 @@
         <item name="android:background">@drawable/candidate_feedback_background</item>
     </style>
     <style name="CandidateViewStyle" parent="SuggestionsStripBackgroundStyle">
-        <item name="autoCorrectHighlight">autoCorrectBold</item>
+        <item name="suggestionStripOption">autoCorrectBold</item>
         <item name="colorTypedWord">#FFFFFFFF</item>
         <item name="colorAutoCorrect">#FFFCAE00</item>
         <item name="colorSuggested">#FFFCAE00</item>
@@ -188,10 +188,10 @@
         <item name="android:background">@drawable/keyboard_popup_panel_background_holo</item>
     </style>
     <style name="CandidateViewStyle.IceCreamSandwich" parent="SuggestionsStripBackgroundStyle.IceCreamSandwich">
-        <item name="autoCorrectHighlight">autoCorrectBold</item>
-        <item name="colorTypedWord">#FFFFFFFF</item>
-        <item name="colorAutoCorrect">#FF3DC8FF</item>
-        <item name="colorSuggested">#FFFFFFFF</item>
+        <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item>
+        <item name="colorTypedWord">#FFBCBEC0</item>
+        <item name="colorAutoCorrect">#FF0099CC</item>
+        <item name="colorSuggested">#FFA7A9AC</item>
         <item name="candidateCountInStrip">@integer/candidate_count_in_strip</item>
         <item name="centerCandidatePercentile">@integer/center_candidate_percentile</item>
     </style>
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 05b6837..15a3d1d 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -96,25 +96,21 @@
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelOption="fontNormal"
         latin:parentStyle="functionalKeyStyle" />
     <key-style
         latin:styleName="toAlphaKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
         latin:keyLabel="@string/label_to_alpha_key"
-        latin:keyLabelOption="fontNormal"
         latin:parentStyle="functionalKeyStyle" />
     <key-style
         latin:styleName="toMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_more_symbol_for_tablet_key"
-        latin:keyLabelOption="fontNormal"
         latin:parentStyle="functionalKeyStyle" />
     <key-style
         latin:styleName="backFromMoreSymbolKeyStyle"
         latin:code="@integer/key_shift"
         latin:keyLabel="@string/label_to_symbol_key"
-        latin:keyLabelOption="fontNormal"
         latin:parentStyle="functionalKeyStyle" />
     <key-style
         latin:styleName="comKeyStyle"
diff --git a/java/res/xml-sw600dp/kbd_qwerty_row4.xml b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
index f22b69f..4c978cb 100644
--- a/java/res/xml-sw600dp/kbd_qwerty_row4.xml
+++ b/java/res/xml-sw600dp/kbd_qwerty_row4.xml
@@ -26,7 +26,6 @@
     >
         <Key
             latin:keyStyle="toSymbolKeyStyle"
-            latin:keyLabelOption="alignLeft"
             latin:keyWidth="13.0%p" />
         <Key
             latin:keyStyle="tabKeyStyle" />
diff --git a/java/res/xml-sw600dp/kbd_rows_symbols.xml b/java/res/xml-sw600dp/kbd_rows_symbols.xml
index 4f6a9bc..420e46c 100644
--- a/java/res/xml-sw600dp/kbd_rows_symbols.xml
+++ b/java/res/xml-sw600dp/kbd_rows_symbols.xml
@@ -147,7 +147,6 @@
     >
         <Key
             latin:keyStyle="toAlphaKeyStyle"
-            latin:keyLabelOption="alignLeft"
             latin:keyWidth="13.0%p" />
         <Key
             latin:keyStyle="tabKeyStyle" />
diff --git a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
index 1dca8c4..2909acb 100644
--- a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
+++ b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml
@@ -133,7 +133,6 @@
     >
         <Key
             latin:keyStyle="toAlphaKeyStyle"
-            latin:keyLabelOption="alignLeft"
             latin:keyWidth="13.0%p" />
         <Key
             latin:keyStyle="tabKeyStyle" />
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index d0a2f86..2e4988f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -113,14 +113,6 @@
                 false, F2KEY_MODE_NONE, false, false, false);
     }
 
-    public KeyboardId cloneWithNewGeometry(int orientation, int width) {
-        if (mWidth == width)
-            return this;
-        return new KeyboardId(mXmlName, mXmlId, mLocale, orientation, width, mMode, mAttribute,
-                mHasSettingsKey, mF2KeyMode, mClobberSettingsKey, mShortcutKeyEnabled,
-                mHasShortcutKey);
-    }
-
     public int getXmlId() {
         return mXmlId;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 9937937..8bf8280 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -20,7 +20,7 @@
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.InflateException;
@@ -39,7 +39,6 @@
 import com.android.inputmethod.latin.Utils;
 
 import java.lang.ref.SoftReference;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Locale;
 
@@ -78,9 +77,6 @@
     private KeyboardId mCurrentId;
     private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
             new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
-    // TODO: Remove this cache object when {@link DisplayMetrics} has actual window width excluding
-    // system navigation bar.
-    private WindowWidthCache mWindowWidthCache;
 
     private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState();
 
@@ -105,77 +101,6 @@
 
     private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
 
-    private static class WindowWidthCache {
-        private final InputMethodService mService;
-        private final Resources mResources;
-        private final boolean mIsRegistered[] = new boolean[Configuration.ORIENTATION_SQUARE + 1];
-        private final int mWidth[] = new int[Configuration.ORIENTATION_SQUARE + 1];
-
-        public WindowWidthCache(InputMethodService service) {
-            mService = service;
-            mResources = service.getResources();
-
-            Arrays.fill(mIsRegistered, false);
-            Arrays.fill(mWidth, 0);
-        }
-
-        private int getCurrentWindowWidth() {
-            return mService.getWindow().getWindow().getDecorView().getWidth();
-        }
-
-        public int getWidth(Configuration conf) {
-            final int orientation = conf.orientation;
-            try {
-                final int width = mWidth[orientation];
-                if (mIsRegistered[orientation] || width > 0) {
-                    // Return registered or cached window width for this orientation.
-                    return width;
-                }
-                // Fall through
-            } catch (IndexOutOfBoundsException e) {
-                Log.w(TAG, "unknwon orientation value " + orientation);
-                // Fall through
-            }
-
-            // Return screen width as default window width.
-            return mResources.getDisplayMetrics().widthPixels;
-        }
-
-        public int getWidthOnSizeChanged(Configuration conf) {
-            final int orientation = conf.orientation;
-            try {
-                if (mIsRegistered[orientation]) {
-                    // Return registered window width for this orientation.
-                    return mWidth[orientation];
-                }
-
-                // Cache the current window width without registering.
-                final int width = getCurrentWindowWidth();
-                mWidth[orientation] = width;
-                return width;
-            } catch (IndexOutOfBoundsException e) {
-                Log.w(TAG, "unknwon orientation value " + orientation);
-                return 0;
-            }
-        }
-
-        public void registerWidth() {
-            final int orientation = mResources.getConfiguration().orientation;
-            try {
-                if (!mIsRegistered[orientation]) {
-                    final int width = getCurrentWindowWidth();
-                    if (width > 0) {
-                        // Register current window width.
-                        mWidth[orientation] = width;
-                        mIsRegistered[orientation] = true;
-                    }
-                }
-            } catch (IndexOutOfBoundsException e) {
-                Log.w(TAG, "unknwon orientation value " + orientation);
-            }
-        }
-    }
-
     public class KeyboardLayoutState {
         private boolean mIsValid;
         private boolean mIsAlphabetMode;
@@ -247,7 +172,6 @@
         mResources = ims.getResources();
         mPrefs = prefs;
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
-        mWindowWidthCache = new WindowWidthCache(ims);
         setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
         prefs.registerOnSharedPreferenceChangeListener(this);
     }
@@ -298,26 +222,6 @@
         mIsAutoCorrectionActive = false;
     }
 
-    public void registerWindowWidth() {
-        mWindowWidthCache.registerWidth();
-    }
-
-    @SuppressWarnings("unused")
-    public void onSizeChanged(int w, int h, int oldw, int oldh) {
-        // TODO: This hack should be removed when display metric returns a proper width.
-        // Until then, the behavior of KeyboardSwitcher is suboptimal on a device that has a
-        // vertical system navigation bar in landscape screen orientation, for instance.
-        final Configuration conf = mResources.getConfiguration();
-        final int width = mWindowWidthCache.getWidthOnSizeChanged(conf);
-        // If the window width hasn't fixed yet or keyboard doesn't exist, nothing to do with.
-        if (width == 0 || mCurrentId == null)
-            return;
-        // Reload keyboard with new width.
-        final KeyboardId newId = mCurrentId.cloneWithNewGeometry(conf.orientation, width);
-        mInputMethodService.mHandler.postRestoreKeyboardLayout();
-        setKeyboard(getKeyboard(newId));
-    }
-
     private void setKeyboard(final Keyboard keyboard) {
         final Keyboard oldKeyboard = mKeyboardView.getKeyboard();
         mKeyboardView.setKeyboard(keyboard);
@@ -402,7 +306,7 @@
             break;
         }
 
-        final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled(editorInfo);
+        final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
         final boolean noMicrophone = Utils.inPrivateImeOptions(
                 mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
                 || Utils.inPrivateImeOptions(
@@ -416,10 +320,11 @@
         final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
         final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
         final Configuration conf = mResources.getConfiguration();
+        final DisplayMetrics dm = mResources.getDisplayMetrics();
 
         return new KeyboardId(
                 mResources.getResourceEntryName(xmlId), xmlId, mSubtypeSwitcher.getInputLocale(),
-                conf.orientation, mWindowWidthCache.getWidth(conf), mode, editorInfo,
+                conf.orientation, dm.widthPixels, mode, editorInfo,
                 hasSettingsKey, f2KeyMode, noSettingsKey, voiceKeyEnabled, hasShortcutKey);
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index 12aadcb..e0c6bbb 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -266,12 +266,6 @@
         return mKeyTimerHandler;
     }
 
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        // TODO: Should notify InputMethodService instead?
-        KeyboardSwitcher.getInstance().onSizeChanged(w, h, oldw, oldh);
-    }
-
     /**
      * Attaches a keyboard to this view. The keyboard can be switched at any time and the
      * view will re-layout itself to accommodate the keyboard.
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index f499bc0..d46b4b5 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -272,9 +272,10 @@
         private static final int AUTO_CORRECT_BOLD = 0x01;
         private static final int AUTO_CORRECT_UNDERLINE = 0x02;
         private static final int AUTO_CORRECT_INVERT = 0x04;
+        private static final int VALID_TYPED_WORD_BOLD = 0x08;
 
         private final TextPaint mPaint;
-        private final int mAutoCorrectHighlight;
+        private final int mSuggestionStripOption;
 
         private final ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>();
 
@@ -285,7 +286,7 @@
             super(words, dividers, infos);
             final TypedArray a = context.obtainStyledAttributes(
                     attrs, R.styleable.CandidateView, defStyle, R.style.CandidateViewStyle);
-            mAutoCorrectHighlight = a.getInt(R.styleable.CandidateView_autoCorrectHighlight, 0);
+            mSuggestionStripOption = a.getInt(R.styleable.CandidateView_suggestionStripOption, 0);
             mColorTypedWord = a.getColor(R.styleable.CandidateView_colorTypedWord, 0);
             mColorAutoCorrect = a.getColor(R.styleable.CandidateView_colorAutoCorrect, 0);
             mColorSuggestedCandidate = a.getColor(R.styleable.CandidateView_colorSuggested, 0);
@@ -313,15 +314,23 @@
             return mColorTypedWord;
         }
 
-        private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) {
-            if (!isAutoCorrect)
+        private CharSequence getStyledCandidateWord(SuggestedWords suggestions, int pos) {
+            final CharSequence word = suggestions.getWord(pos);
+            final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
+            final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid;
+            if (!isAutoCorrect && !isTypedWordValid)
                 return word;
+
             final int len = word.length();
             final Spannable spannedWord = new SpannableString(word);
-            if ((mAutoCorrectHighlight & AUTO_CORRECT_BOLD) != 0)
+            final int option = mSuggestionStripOption;
+            if ((isAutoCorrect && (option & AUTO_CORRECT_BOLD) != 0)
+                    || (isTypedWordValid && (option & VALID_TYPED_WORD_BOLD) != 0)) {
                 spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-            if ((mAutoCorrectHighlight & AUTO_CORRECT_UNDERLINE) != 0)
+            }
+            if (isAutoCorrect && (option & AUTO_CORRECT_UNDERLINE) != 0) {
                 spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+            }
             return spannedWord;
         }
 
@@ -370,7 +379,7 @@
         }
 
         public CharSequence getInvertedText(CharSequence text) {
-            if ((mAutoCorrectHighlight & AUTO_CORRECT_INVERT) == 0)
+            if ((mSuggestionStripOption & AUTO_CORRECT_INVERT) == 0)
                 return null;
             final int len = text.length();
             final Spannable word = new SpannableString(text);
@@ -457,9 +466,7 @@
             mTexts.clear();
             final int count = Math.min(suggestions.size(), countInStrip);
             for (int pos = 0; pos < count; pos++) {
-                final CharSequence word = suggestions.getWord(pos);
-                final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions);
-                final CharSequence styled = getStyledCandidateWord(word, isAutoCorrect);
+                final CharSequence styled = getStyledCandidateWord(suggestions, pos);
                 mTexts.add(styled);
             }
             for (int pos = count; pos < countInStrip; pos++) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a932f03..afbdd36 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -2027,7 +2027,6 @@
     @Override
     public void onPress(int primaryCode, boolean withSliding) {
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
-        switcher.registerWindowWidth();
         if (switcher.isVibrateAndSoundFeedbackRequired()) {
             vibrate();
             playKeyClick(primaryCode);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4c2627b..87a713f 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -53,7 +53,7 @@
 public class Settings extends InputMethodSettingsActivity
         implements SharedPreferences.OnSharedPreferenceChangeListener,
         DialogInterface.OnDismissListener, OnPreferenceClickListener {
-    private static final String TAG = "Settings";
+    private static final String TAG = Settings.class.getSimpleName();
 
     public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
     public static final String PREF_VIBRATE_ON = "vibrate_on";
@@ -182,8 +182,9 @@
             mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
             final boolean defaultShowSettingsKey = res.getBoolean(
                     R.bool.config_default_show_settings_key);
-            mShowSettingsKey = prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY,
-                    defaultShowSettingsKey);
+            mShowSettingsKey = isShowSettingsKeyOption(res)
+                    ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
+                    : defaultShowSettingsKey;
             final String voiceModeMain = res.getString(R.string.voice_mode_main);
             final String voiceModeOff = res.getString(R.string.voice_mode_off);
             final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain);
@@ -292,7 +293,12 @@
             return builder.setIsPunctuationSuggestions().build();
         }
 
-        public boolean isSettingsKeyEnabled(EditorInfo attribute) {
+        public static boolean isShowSettingsKeyOption(final Resources resources) {
+            return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
+
+        }
+
+        public boolean isSettingsKeyEnabled() {
             return mShowSettingsKey;
         }
 
@@ -386,9 +392,7 @@
         final PreferenceGroup textCorrectionGroup =
                 (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY);
 
-        final boolean showSettingsKeyOption = res.getBoolean(
-                R.bool.config_enable_show_settings_key_option);
-        if (!showSettingsKeyOption) {
+        if (!Values.isShowSettingsKeyOption(res)) {
             generalSettings.removePreference(mShowSettingsKeyPreference);
         }
 
@@ -445,8 +449,7 @@
         if (null == mKeyPreviewPopupDismissDelay.getValue()) {
             mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue);
         }
-        mKeyPreviewPopupDismissDelay.setEnabled(
-                Settings.Values.isKeyPreviewPopupEnabled(prefs, res));
+        mKeyPreviewPopupDismissDelay.setEnabled(Values.isKeyPreviewPopupEnabled(prefs, res));
 
         final PreferenceScreen dictionaryLink =
                 (PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index ec82f9e..502ebb5 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -23,6 +23,7 @@
 import android.util.Log;
 import android.view.textservice.SuggestionsInfo;
 import android.view.textservice.TextInfo;
+import android.text.TextUtils;
 
 import com.android.inputmethod.compat.ArraysCompatUtils;
 import com.android.inputmethod.keyboard.Key;
@@ -36,6 +37,7 @@
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.WordComposer;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Locale;
@@ -50,7 +52,9 @@
     private static final boolean DBG = false;
     private static final int POOL_SIZE = 2;
 
-    private final static String[] emptyArray = new String[0];
+    private final static String[] EMPTY_STRING_ARRAY = new String[0];
+    private final static SuggestionsInfo EMPTY_SUGGESTIONS_INFO =
+            new SuggestionsInfo(0, EMPTY_STRING_ARRAY);
     private Map<String, DictionaryPool> mDictionaryPools =
             Collections.synchronizedMap(new TreeMap<String, DictionaryPool>());
     private Map<String, Dictionary> mUserDictionaries =
@@ -63,14 +67,15 @@
 
     private static class SuggestionsGatherer implements WordCallback {
         private final int DEFAULT_SUGGESTION_LENGTH = 16;
-        private final String[] mSuggestions;
+        private final ArrayList<CharSequence> mSuggestions;
         private final int[] mScores;
         private final int mMaxLength;
         private int mLength = 0;
+        private boolean mSeenSuggestions = false;
 
         SuggestionsGatherer(final int maxLength) {
             mMaxLength = maxLength;
-            mSuggestions = new String[mMaxLength];
+            mSuggestions = new ArrayList<CharSequence>(maxLength + 1);
             mScores = new int[mMaxLength];
         }
 
@@ -82,30 +87,37 @@
             // if it doesn't. See documentation for binarySearch.
             final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1;
 
+            mSeenSuggestions = true;
             if (mLength < mMaxLength) {
                 final int copyLen = mLength - insertIndex;
                 ++mLength;
                 System.arraycopy(mScores, insertIndex, mScores, insertIndex + 1, copyLen);
-                System.arraycopy(mSuggestions, insertIndex, mSuggestions, insertIndex + 1, copyLen);
+                mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
             } else {
                 if (insertIndex == 0) return true;
                 System.arraycopy(mScores, 1, mScores, 0, insertIndex);
-                System.arraycopy(mSuggestions, 1, mSuggestions, 0, insertIndex);
+                mSuggestions.add(insertIndex, new String(word, wordOffset, wordLength));
+                mSuggestions.remove(0);
             }
             mScores[insertIndex] = score;
-            mSuggestions[insertIndex] = new String(word, wordOffset, wordLength);
 
             return true;
         }
 
         public String[] getGatheredSuggestions() {
-            if (0 == mLength) return null;
+            if (!mSeenSuggestions) return null;
+            if (0 == mLength) return EMPTY_STRING_ARRAY;
 
-            final String[] results = new String[mLength];
-            for (int i = mLength - 1; i >= 0; --i) {
-                results[mLength - i - 1] = mSuggestions[i];
+            if (DBG) {
+                if (mLength != mSuggestions.size()) {
+                    Log.e(TAG, "Suggestion size is not the same as stored mLength");
+                }
             }
-            return results;
+            Collections.reverse(mSuggestions);
+            Utils.removeDupes(mSuggestions);
+            // This returns a String[], while toArray() returns an Object[] which cannot be cast
+            // into a String[].
+            return mSuggestions.toArray(EMPTY_STRING_ARRAY);
         }
     }
 
@@ -153,10 +165,14 @@
     private class AndroidSpellCheckerSession extends Session {
         // Immutable, but need the locale which is not available in the constructor yet
         DictionaryPool mDictionaryPool;
+        // Likewise
+        Locale mLocale;
 
         @Override
         public void onCreate() {
-            mDictionaryPool = getDictionaryPool(getLocale());
+            final String localeString = getLocale();
+            mDictionaryPool = getDictionaryPool(localeString);
+            mLocale = Utils.constructLocaleFromString(localeString);
         }
 
         // Note : this must be reentrant
@@ -170,6 +186,8 @@
                 final int suggestionsLimit) {
             final String text = textInfo.getText();
 
+            if (TextUtils.isEmpty(text)) return EMPTY_SUGGESTIONS_INFO;
+
             final SuggestionsGatherer suggestionsGatherer =
                     new SuggestionsGatherer(suggestionsLimit);
             final WordComposer composer = new WordComposer();
@@ -194,12 +212,32 @@
                 dictInfo.mDictionary.getWords(composer, suggestionsGatherer,
                         dictInfo.mProximityInfo);
                 isInDict = dictInfo.mDictionary.isValidWord(text);
+                if (!isInDict && Character.isUpperCase(text.codePointAt(0))) {
+                    // If the first char is not uppercase, then the word is either all lower case,
+                    // in which case we already tested it, or mixed case, in which case we don't
+                    // want to test a lower-case version of it. Hence the test above.
+                    // Also note that by isEmpty() test at the top of the method codePointAt(0) is
+                    // guaranteed to be there.
+                    final int len = text.codePointCount(0, text.length());
+                    int capsCount = 1;
+                    for (int i = 1; i < len; ++i) {
+                        if (1 != capsCount && i != capsCount) break;
+                        if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
+                    }
+                    // We know the first char is upper case. So we want to test if either everything
+                    // else is lower case, or if everything else is upper case. If the string is
+                    // exactly one char long, then we will arrive here with capsCount 0, and this is
+                    // correct, too.
+                    if (1 == capsCount || len == capsCount) {
+                        isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
+                    }
+                }
                 if (!mDictionaryPool.offer(dictInfo)) {
                     Log.e(TAG, "Can't re-insert a dictionary into its pool");
                 }
             } catch (InterruptedException e) {
                 // I don't think this can happen.
-                return new SuggestionsInfo(0, new String[0]);
+                return EMPTY_SUGGESTIONS_INFO;
             }
 
             final String[] suggestions = suggestionsGatherer.getGatheredSuggestions();