Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/values-es/donottranslate-more-keys.xml b/java/res/values-es/donottranslate-more-keys.xml
index 4833d69..f56b1d5 100644
--- a/java/res/values-es/donottranslate-more-keys.xml
+++ b/java/res/values-es/donottranslate-more-keys.xml
@@ -69,5 +69,5 @@
     <string name="more_keys_for_c">&#x00E7;,&#x0107;,&#x010D;</string>
     <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK
          U+00BF: "¿" INVERTED QUESTION MARK -->
-    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',-,&#x00A1;,!,&#x00BF;,\\,,\?,\@,&amp;,+,;,:,/,(,)"</string>
+    <string name="more_keys_for_punctuation">"!fixedColumnOrder!7,#,-,&#x00A1;,!,&#x00BF;,\\,,\?,\\%,+,;,:,/,(,),\@,&amp;,\",\'"</string>
 </resources>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index f91b0a3..a5d590e 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -355,7 +355,8 @@
             <enum name="phone" value="4" />
             <enum name="number" value="5" />
         </attr>
-        <attr name="navigateAction" format="boolean" />
+        <attr name="navigateNext" format="boolean" />
+        <attr name="navigatePrevious" format="boolean" />
         <attr name="passwordInput" format="boolean" />
         <attr name="clobberSettingsKey" format="boolean" />
         <attr name="shortcutKeyEnabled" format="boolean" />
diff --git a/java/res/values/donottranslate-more-keys.xml b/java/res/values/donottranslate-more-keys.xml
index f1c2d2b..0581a61 100644
--- a/java/res/values/donottranslate-more-keys.xml
+++ b/java/res/values/donottranslate-more-keys.xml
@@ -65,7 +65,7 @@
     <string name="more_keys_for_currency_pound">&#x00A2;,$,&#x20AC;,&#x00A5;,&#x20B1;</string>
     <string name="more_keys_for_currency_general">&#x00A2;,$,&#x20AC;,&#x00A3;,&#x00A5;,&#x20B1;</string>
     <string name="more_keys_for_smiley">"!fixedColumnOrder!5,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ "</string>
-    <string name="more_keys_for_punctuation">"!fixedColumnOrder!7,\",\',-,:,!,\\,,\?,\@,&amp;,+,;,/,(,)"</string>
+    <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,\\,,\?,\@,&amp;,\\%,+,;,/,(,)"</string>
     <string name="keyhintlabel_for_punctuation"></string>
     <string name="keylabel_for_popular_domain">".com"</string>
     <!-- popular web domains for the locale - most popular, displayed on the keyboard -->
@@ -118,6 +118,8 @@
     <string name="settings_as_more_key">\@icon/settingsKey|\@integer/key_settings</string>
     <string name="keylabel_for_comma">,</string>
     <string name="more_keys_for_comma"></string>
+    <string name="action_next_as_more_key">\@string/label_next_key|\@integer/key_action_next</string>
+    <string name="action_previous_as_more_key">\@string/label_previous_key|\@integer/key_action_previous</string>
     <string name="keylabel_for_symbols_question">\?</string>
     <string name="keylabel_for_symbols_semicolon">;</string>
     <string name="keylabel_for_symbols_percent">%</string>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 69d923a..94da946 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -20,17 +20,17 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Symbols that are suggested between words -->
     <string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string>
-    <!-- Symbols that should be swapped with a magic space -->
-    <string name="magic_space_swapping_symbols">.,;:!?)]}\"</string>
-    <!-- Symbols that should strip a magic space -->
-    <string name="magic_space_stripping_symbols">"&#x0009;&#x0020;\n/_\'-"</string>
-    <!-- Symbols that should convert magic spaces into real space -->
-    <string name="magic_space_promoting_symbols">([*&amp;@{&lt;&gt;+=|</string>
+    <!-- Symbols that should be swapped with a weak space -->
+    <string name="weak_space_swapping_symbols">.,;:!?)]}\"</string>
+    <!-- Symbols that should strip a weak space -->
+    <string name="weak_space_stripping_symbols">"&#x0009;&#x0020;\n/_\'-"</string>
+    <!-- Symbols that should convert weak spaces into real space -->
+    <string name="weak_space_promoting_symbols">([*&amp;@{&lt;&gt;+=|</string>
     <!-- Symbols that do NOT separate words -->
     <string name="symbols_excluded_from_word_separators">\'-</string>
     <!-- Word separator list is the union of all symbols except those that are not separators:
-    magic_space_swapping_symbols | magic_space_stripping_symbols |
-            magic_space_neutral_symbols \ symbols_excluded_from_word_separators -->
+    weak_space_swapping_symbols | weak_space_stripping_symbols
+            \ symbols_excluded_from_word_separators -->
     <!-- Symbol characters list that should switch back to the main layout -->
     <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK
          U+2019: "’" RIGHT SINGLE QUOTATION MARK
diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml
index c85c022..7f9e4bd 100644
--- a/java/res/values/keycodes.xml
+++ b/java/res/values/keycodes.xml
@@ -30,5 +30,7 @@
     <integer name="key_settings">-5</integer>
     <integer name="key_shortcut">-6</integer>
     <integer name="key_action_enter">-7</integer>
-    <integer name="key_unspecified">-9</integer>
+    <integer name="key_action_next">-8</integer>
+    <integer name="key_action_previous">-9</integer>
+    <integer name="key_unspecified">-10</integer>
 </resources>
diff --git a/java/res/xml-ka/keyboard_set.xml b/java/res/xml-ka/keyboard_set.xml
new file mode 100644
index 0000000..1b0bc2d
--- /dev/null
+++ b/java/res/xml-ka/keyboard_set.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<KeyboardSet
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    latin:keyboardLocale="ka">
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_georgian" />
+    <Element
+        latin:elementName="symbols"
+        latin:elementKeyboard="@xml/kbd_symbols" />
+    <Element
+        latin:elementName="symbolsShifted"
+        latin:elementKeyboard="@xml/kbd_symbols_shift" />
+    <Element
+        latin:elementName="phone"
+        latin:elementKeyboard="@xml/kbd_phone" />
+    <Element
+        latin:elementName="phoneSymbols"
+        latin:elementKeyboard="@xml/kbd_phone_symbols" />
+    <Element
+        latin:elementName="number"
+        latin:elementKeyboard="@xml/kbd_number" />
+</KeyboardSet>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index bb75b1c..2fa8b38 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -73,7 +73,7 @@
         latin:keyActionFlags="isRepeatable|noKeyPreview"
         latin:backgroundType="functional" />
     <include
-        latin:keyboardLayout="@xml/key_styles_enter_tablet" />
+        latin:keyboardLayout="@xml/key_styles_enter" />
     <key-style
         latin:styleName="spaceKeyStyle"
         latin:code="@integer/key_space"
@@ -102,12 +102,27 @@
         latin:keyIcon="iconSettingsKey"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:backgroundType="functional" />
-    <key-style
-        latin:styleName="tabKeyStyle"
-        latin:code="@integer/key_tab"
-        latin:keyIcon="iconTabKey"
-        latin:keyIconPreview="iconPreviewTabKey"
-        latin:backgroundType="functional" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            latin:navigatePrevious="true"
+        >
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="@integer/key_action_previous"
+                latin:keyIcon="iconTabKey"
+                latin:keyIconPreview="iconPreviewTabKey"
+                latin:backgroundType="functional" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="@integer/key_tab"
+                latin:keyIcon="iconTabKey"
+                latin:keyIconPreview="iconPreviewTabKey"
+                latin:backgroundType="functional" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
diff --git a/java/res/xml-sw600dp/rows_georgian.xml b/java/res/xml-sw600dp/rows_georgian.xml
new file mode 100644
index 0000000..c04df48
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_georgian.xml
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="9.0%p"
+    >
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="Q"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10ED: "ჭ" GEORGIAN LETTER CHAR -->
+                <Key
+                    latin:keyLabel="&#x10ED;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="E"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E6: "ღ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D7: "თ" GEORGIAN LETTER TAN -->
+                <Key
+                    latin:keyLabel="&#x10D7;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="Y"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="U"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="I"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="O"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="P"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10E5: "ქ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E5;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EC: "წ" GEORGIAN LETTER CIL -->
+                <Key
+                    latin:keyLabel="&#x10EC;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D4: "ე" GEORGIAN LETTER EN
+                     U+10F1: "ჱ" GEORGIAN LETTER HE -->
+                <Key
+                    latin:keyLabel="&#x10D4;"
+                    latin:moreKeys="&#x10F1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E0: "რ" GEORGIAN LETTER RAE -->
+                <Key
+                    latin:keyLabel="&#x10E0;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E2: "ტ" GEORGIAN LETTER TAR -->
+                <Key
+                    latin:keyLabel="&#x10E2;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E7: "ყ" GEORGIAN LETTER QAR
+                     U+10F8: "ჸ" GEORGIAN LETTER ELIFI -->
+                <Key
+                    latin:keyLabel="&#x10E7;"
+                    latin:moreKeys="&#x10F8;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E3: "უ" GEORGIAN LETTER UN -->
+                <Key
+                    latin:keyLabel="&#x10E3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D8: "ი" GEORGIAN LETTER IN
+                     U+10F2: "ჲ" GEORGIAN LETTER HIE -->
+                <Key
+                    latin:keyLabel="&#x10D8;"
+                    latin:moreKeys="&#x10F2;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DD: "ო" GEORGIAN LETTER ON -->
+                <Key
+                    latin:keyLabel="&#x10DD;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DE: "პ" GEORGIAN LETTER PAR -->
+                <Key
+                    latin:keyLabel="&#x10DE;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyXPos="-10.0%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="9.0%p"
+    >
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="A"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyXPos="4.5%p" />
+                <!-- U+10E8: "შ" GEORGIAN LETTER SHIN -->
+                <Key
+                    latin:keyLabel="&#x10E8;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="D"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="F"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="G"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="H"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DF: "ჟ" GEORGIAN LETTER ZHAR -->
+                <Key
+                    latin:keyLabel="&#x10DF;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="K"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="L"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D0: "ა" GEORGIAN LETTER AN
+                     U+10FA: "ჺ" GEORGIAN LETTER AIN -->
+                <Key
+                    latin:keyLabel="&#x10D0;"
+                    latin:moreKeys="&#x10FA;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyXPos="4.5%p" />
+                <!-- U+10E1: "ს" GEORGIAN LETTER SAN -->
+                <Key
+                    latin:keyLabel="&#x10E1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D3: "დ" GEORGIAN LETTER DON -->
+                <Key
+                    latin:keyLabel="&#x10D3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E4: "ფ" GEORGIAN LETTER PHAR
+                     U+10F6: "ჶ" GEORGIAN LETTER FI -->
+                <Key
+                    latin:keyLabel="&#x10E4;"
+                    latin:moreKeys="&#x10F6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D2: "გ" GEORGIAN LETTER GAN
+                     U+10F9: "ჹ" GEORGIAN LETTER TURNED GAN -->
+                <Key
+                    latin:keyLabel="&#x10D2;"
+                    latin:moreKeys="&#x10F9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10F0: "ჰ" GEORGIAN LETTER HAE
+                     U+10F5: "ჵ" GEORGIAN LETTER HOE -->
+                <Key
+                    latin:keyLabel="&#x10F0;"
+                    latin:moreKeys="&#x10F5;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EF: "ჯ" GEORGIAN LETTER JHAN
+                     U+10F7: "ჷ" GEORGIAN LETTER YN -->
+                <Key
+                    latin:keyLabel="&#x10EF;"
+                    latin:moreKeys="&#x10F7;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D9: "კ" GEORGIAN LETTER KAN -->
+                <Key
+                    latin:keyLabel="&#x10D9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DA: "ლ" GEORGIAN LETTER LAS -->
+                <Key
+                    latin:keyLabel="&#x10DA;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyXPos="-14.6%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="8.9%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <!-- U+10EB: "ძ" GEORGIAN LETTER JIL -->
+                <Key
+                    latin:keyLabel="&#x10EB;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="X"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E9: "ჩ" GEORGIAN LETTER CHIN -->
+                <Key
+                    latin:keyLabel="&#x10E9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="V"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="B"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="N"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="M"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D6: "ზ" GEORGIAN LETTER ZEN -->
+                <Key
+                    latin:keyLabel="&#x10D6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EE: "ხ" GEORGIAN LETTER XAN
+                     U+10F4: "ჴ" GEORGIAN LETTER HAR -->
+                <Key
+                    latin:keyLabel="&#x10EE;"
+                    latin:moreKeys="&#x10F4;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EA: "ც" GEORGIAN LETTER CAN -->
+                <Key
+                    latin:keyLabel="&#x10EA;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D5: "ვ" GEORGIAN LETTER VIN
+                     U+10F3: "ჳ" GEORGIAN LETTER WE -->
+                <Key
+                    latin:keyLabel="&#x10D5;"
+                    latin:moreKeys="&#x10F3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D1: "ბ" GEORGIAN LETTER BAN -->
+                <Key
+                    latin:keyLabel="&#x10D1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DC: "ნ" GEORGIAN LETTER NAR
+                     U+10FC: "ჼ" MODIFIER LETTER GEORGIAN NAR -->
+                <Key
+                    latin:keyLabel="&#x10DC;"
+                    latin:moreKeys="&#x10FC;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DB: "მ" GEORGIAN LETTER MAN -->
+                <Key
+                    latin:keyLabel="&#x10DB;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <include
+            latin:keyboardLayout="@xml/keys_comma_period" />
+        <include
+            latin:keyboardLayout="@xml/key_smiley"
+            latin:keyXPos="-8.9%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
index 9da0d1f..5c35f1c 100644
--- a/java/res/xml-sw768dp/key_styles_common.xml
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -72,7 +72,7 @@
         latin:keyActionFlags="isRepeatable|noKeyPreview"
         latin:backgroundType="functional" />
     <include
-        latin:keyboardLayout="@xml/key_styles_enter_tablet" />
+        latin:keyboardLayout="@xml/key_styles_enter" />
     <key-style
         latin:styleName="spaceKeyStyle"
         latin:code="@integer/key_space"
@@ -101,12 +101,27 @@
         latin:keyIcon="iconSettingsKey"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:backgroundType="functional" />
-    <key-style
-        latin:styleName="tabKeyStyle"
-        latin:code="@integer/key_tab"
-        latin:keyLabel="@string/label_tab_key"
-        latin:keyLabelFlags="fontNormal|preserveCase"
-        latin:backgroundType="functional" />
+    <switch>
+        <case
+            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            latin:navigatePrevious="true"
+        >
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="@integer/key_action_previous"
+                latin:keyLabel="@string/label_tab_key"
+                latin:keyLabelFlags="fontNormal|preserveCase"
+                latin:backgroundType="functional" />
+        </case>
+        <default>
+            <key-style
+                latin:styleName="tabKeyStyle"
+                latin:code="@integer/key_tab"
+                latin:keyLabel="@string/label_tab_key"
+                latin:keyLabelFlags="fontNormal|preserveCase"
+                latin:backgroundType="functional" />
+        </default>
+    </switch>
     <key-style
         latin:styleName="toSymbolKeyStyle"
         latin:code="@integer/key_switch_alpha_symbol"
diff --git a/java/res/xml-sw768dp/rows_georgian.xml b/java/res/xml-sw768dp/rows_georgian.xml
new file mode 100644
index 0000000..d991033
--- /dev/null
+++ b/java/res/xml-sw768dp/rows_georgian.xml
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="8.282%p"
+    >
+        <Key
+            latin:keyStyle="tabKeyStyle"
+            latin:keyLabelFlags="alignLeft"
+            latin:keyWidth="7.969%p" />
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="Q"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10ED: "ჭ" GEORGIAN LETTER CHAR -->
+                <Key
+                    latin:keyLabel="&#x10ED;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="E"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E6: "ღ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D7: "თ" GEORGIAN LETTER TAN -->
+                <Key
+                    latin:keyLabel="&#x10D7;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="Y"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="U"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="I"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="O"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="P"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10E5: "ქ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E5;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EC: "წ" GEORGIAN LETTER CIL -->
+                <Key
+                    latin:keyLabel="&#x10EC;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D4: "ე" GEORGIAN LETTER EN
+                     U+10F1: "ჱ" GEORGIAN LETTER HE -->
+                <Key
+                    latin:keyLabel="&#x10D4;"
+                    latin:moreKeys="&#x10F1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E0: "რ" GEORGIAN LETTER RAE -->
+                <Key
+                    latin:keyLabel="&#x10E0;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E2: "ტ" GEORGIAN LETTER TAR -->
+                <Key
+                    latin:keyLabel="&#x10E2;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E7: "ყ" GEORGIAN LETTER QAR
+                     U+10F8: "ჸ" GEORGIAN LETTER ELIFI -->
+                <Key
+                    latin:keyLabel="&#x10E7;"
+                    latin:moreKeys="&#x10F8;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E3: "უ" GEORGIAN LETTER UN -->
+                <Key
+                    latin:keyLabel="&#x10E3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D8: "ი" GEORGIAN LETTER IN
+                     U+10F2: "ჲ" GEORGIAN LETTER HIE -->
+                <Key
+                    latin:keyLabel="&#x10D8;"
+                    latin:moreKeys="&#x10F2;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DD: "ო" GEORGIAN LETTER ON -->
+                <Key
+                    latin:keyLabel="&#x10DD;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DE: "პ" GEORGIAN LETTER PAR -->
+                <Key
+                    latin:keyLabel="&#x10DE;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyXPos="-9.219%p"
+            latin:keyWidth="fillBoth"/>
+    </Row>
+    <Row
+        latin:keyWidth="8.125%p"
+    >
+        <Key
+            latin:keyStyle="toSymbolKeyStyle"
+            latin:keyLabelFlags="alignLeft"
+            latin:keyWidth="11.172%p"/>
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="A"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E8: "შ" GEORGIAN LETTER SHIN -->
+                <Key
+                    latin:keyLabel="&#x10E8;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="D"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="F"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="G"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="H"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DF: "ჟ" GEORGIAN LETTER ZHAR -->
+                <Key
+                    latin:keyLabel="&#x10DF;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="K"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="L"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D0: "ა" GEORGIAN LETTER AN
+                     U+10FA: "ჺ" GEORGIAN LETTER AIN -->
+                <Key
+                    latin:keyLabel="&#x10D0;"
+                    latin:moreKeys="&#x10FA;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E1: "ს" GEORGIAN LETTER SAN -->
+                <Key
+                    latin:keyLabel="&#x10E1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D3: "დ" GEORGIAN LETTER DON -->
+                <Key
+                    latin:keyLabel="&#x10D3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E4: "ფ" GEORGIAN LETTER PHAR
+                     U+10F6: "ჶ" GEORGIAN LETTER FI -->
+                <Key
+                    latin:keyLabel="&#x10E4;"
+                    latin:moreKeys="&#x10F6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D2: "გ" GEORGIAN LETTER GAN
+                     U+10F9: "ჹ" GEORGIAN LETTER TURNED GAN -->
+                <Key
+                    latin:keyLabel="&#x10D2;"
+                    latin:moreKeys="&#x10F9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10F0: "ჰ" GEORGIAN LETTER HAE
+                     U+10F5: "ჵ" GEORGIAN LETTER HOE -->
+                <Key
+                    latin:keyLabel="&#x10F0;"
+                    latin:moreKeys="&#x10F5;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EF: "ჯ" GEORGIAN LETTER JHAN
+                     U+10F7: "ჷ" GEORGIAN LETTER YN -->
+                <Key
+                    latin:keyLabel="&#x10EF;"
+                    latin:moreKeys="&#x10F7;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D9: "კ" GEORGIAN LETTER KAN -->
+                <Key
+                    latin:keyLabel="&#x10D9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DA: "ლ" GEORGIAN LETTER LAS -->
+                <Key
+                    latin:keyLabel="&#x10DA;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyXPos="-15.704%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <Row
+        latin:keyWidth="8.047%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="13.829%p"/>
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <!-- U+10EB: "ძ" GEORGIAN LETTER JIL -->
+                <Key
+                    latin:keyLabel="&#x10EB;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="X"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E9: "ჩ" GEORGIAN LETTER CHIN -->
+                <Key
+                    latin:keyLabel="&#x10E9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="V"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="B"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="N"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="M"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D6: "ზ" GEORGIAN LETTER ZEN -->
+                <Key
+                    latin:keyLabel="&#x10D6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EE: "ხ" GEORGIAN LETTER XAN
+                     U+10F4: "ჴ" GEORGIAN LETTER HAR -->
+                <Key
+                    latin:keyLabel="&#x10EE;"
+                    latin:moreKeys="&#x10F4;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EA: "ც" GEORGIAN LETTER CAN -->
+                <Key
+                    latin:keyLabel="&#x10EA;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D5: "ვ" GEORGIAN LETTER VIN
+                     U+10F3: "ჳ" GEORGIAN LETTER WE -->
+                <Key
+                    latin:keyLabel="&#x10D5;"
+                    latin:moreKeys="&#x10F3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D1: "ბ" GEORGIAN LETTER BAN -->
+                <Key
+                    latin:keyLabel="&#x10D1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DC: "ნ" GEORGIAN LETTER NAR
+                     U+10FC: "ჼ" MODIFIER LETTER GEORGIAN NAR -->
+                <Key
+                    latin:keyLabel="&#x10DC;"
+                    latin:moreKeys="&#x10FC;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DB: "მ" GEORGIAN LETTER MAN -->
+                <Key
+                    latin:keyLabel="&#x10DB;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <include
+            latin:keyboardLayout="@xml/keys_comma_period" />
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyXPos="-13.750%p"
+            latin:keyWidth="fillBoth" />
+    </Row>
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/key_navigation_tab.xml b/java/res/xml/kbd_georgian.xml
similarity index 62%
rename from java/res/xml/key_navigation_tab.xml
rename to java/res/xml/kbd_georgian.xml
index c77189f..2dc6bf0 100644
--- a/java/res/xml/key_navigation_tab.xml
+++ b/java/res/xml/kbd_georgian.xml
@@ -2,7 +2,7 @@
 <!--
 /*
 **
-** Copyright 2011, The Android Open Source Project
+** Copyright 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.
@@ -18,20 +18,9 @@
 */
 -->
 
-<merge
+<Keyboard
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <switch>
-        <case
-            latin:navigateAction="true"
-        >
-            <Key
-                latin:keyStyle="tabKeyStyle"
-                latin:keyWidth="9.2%p" />
-        </case>
-        <!-- hasSettingsKey="false" and navigateAction="false" -->
-        <default>
-            <!-- No key. -->
-        </default>
-    </switch>
-</merge>
+    <include
+        latin:keyboardLayout="@xml/rows_georgian" />
+</Keyboard>
diff --git a/java/res/xml/key_f1.xml b/java/res/xml/key_f1.xml
deleted file mode 100644
index 6068d25..0000000
--- a/java/res/xml/key_f1.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <switch>
-        <case
-            latin:navigateAction="false"
-        >
-            <switch>
-                <case
-                    latin:mode="url"
-                >
-                    <Key
-                        latin:keyLabel="/"
-                        latin:keyStyle="f1PopupStyle" />
-                </case>
-                <case
-                    latin:mode="email"
-                >
-                    <Key
-                        latin:keyLabel="\@"
-                        latin:keyStyle="f1PopupStyle" />
-                </case>
-                <case
-                    latin:hasShortcutKey="true"
-                >
-                    <Key
-                        latin:keyStyle="shortcutKeyStyle" />
-                </case>
-                <!-- latin:hasShortcutKey="false" -->
-                <default>
-                    <Key
-                        latin:keyLabel="@string/keylabel_for_comma"
-                        latin:keyLabelFlags="hasPopupHint"
-                        latin:additionalMoreKeys="@string/more_keys_for_comma"
-                        latin:keyStyle="f1PopupStyle" />
-                </default>
-            </switch>
-        </case>
-        <!-- TODO: Remove dedicated navigation tab key. -->
-        <!-- navigateAction="true" -->
-        <default>
-            <switch>
-                <case
-                    latin:mode="url"
-                >
-                    <Key
-                        latin:keyLabel="/"
-                        latin:keyWidth="9.2%p"
-                        latin:keyStyle="f1PopupStyle" />
-                </case>
-                <case
-                    latin:mode="email"
-                >
-                    <Key
-                        latin:keyLabel="\@"
-                        latin:keyWidth="9.2%p"
-                        latin:keyStyle="f1PopupStyle" />
-                </case>
-                <case
-                    latin:hasShortcutKey="true"
-                >
-                    <Key
-                        latin:keyStyle="shortcutKeyStyle"
-                        latin:keyWidth="9.2%p" />
-                </case>
-                <!-- hasShortcutKey="false" -->
-                <default>
-                    <Key
-                        latin:keyLabel="@string/keylabel_for_comma"
-                        latin:additionalMoreKeys="@string/more_keys_for_comma"
-                        latin:keyStyle="f1PopupStyle"
-                        latin:keyWidth="9.2%p" />
-                    </default>
-            </switch>
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index eabbdb3..f0ea8ce 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -27,13 +27,13 @@
             latin:clobberSettingsKey="true"
         >
             <key-style
-                latin:styleName="f1PopupStyle"
+                latin:styleName="f1MoreKeysStyle"
                 latin:backgroundType="functional" />
         </case>
         <!-- clobberSettingsKey="false" -->
         <default>
             <key-style
-                latin:styleName="f1PopupStyle"
+                latin:styleName="f1MoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint"
                 latin:moreKeys="@string/settings_as_more_key"
                 latin:backgroundType="functional" />
@@ -77,7 +77,22 @@
         latin:keyActionFlags="isRepeatable|noKeyPreview"
         latin:backgroundType="functional" />
     <include
-        latin:keyboardLayout="@xml/key_styles_enter_phone" />
+        latin:keyboardLayout="@xml/key_styles_enter" />
+    <switch>
+        <!-- Smiley in textShortMessage field.
+             Overrides common enter key style. -->
+        <case
+            latin:mode="im"
+        >
+            <key-style
+                latin:styleName="enterKeyStyle"
+                latin:keyLabel=":-)"
+                latin:keyOutputText=":-) "
+                latin:keyLabelFlags="hasPopupHint"
+                latin:moreKeys="@string/more_keys_for_smiley"
+                latin:backgroundType="functional" />
+        </case>
+    </switch>
     <key-style
         latin:styleName="spaceKeyStyle"
         latin:code="@integer/key_space"
@@ -91,7 +106,7 @@
         latin:keyLabelFlags="preserveCase"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:altCode="@integer/key_space"
-        latin:parentStyle="f1PopupStyle" />
+        latin:parentStyle="f1MoreKeysStyle" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
diff --git a/java/res/xml/key_styles_enter_phone.xml b/java/res/xml/key_styles_enter.xml
similarity index 64%
rename from java/res/xml/key_styles_enter_phone.xml
rename to java/res/xml/key_styles_enter.xml
index af34cb8..4c31c3e 100644
--- a/java/res/xml/key_styles_enter_phone.xml
+++ b/java/res/xml/key_styles_enter.xml
@@ -21,6 +21,60 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
+    <!-- Navigate more keys style -->
+    <switch>
+        <case
+            latin:imeAction="actionNext"
+            latin:navigatePrevious="true"
+        >
+            <key-style
+                latin:styleName="navigateMoreKeysStyle"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
+                latin:moreKeys="@string/action_previous_as_more_key" />
+        </case>
+        <case
+            latin:imeAction="actionPrevious"
+            latin:navigateNext="true"
+        >
+            <key-style
+                latin:styleName="navigateMoreKeysStyle"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
+                latin:moreKeys="@string/action_next_as_more_key" />
+        </case>
+        <!-- imeAction!="actionNext" and imeAction!="actionPrevious" -->
+        <case
+            latin:navigateNext="true"
+            latin:navigatePrevious="true"
+        >
+            <key-style
+                latin:styleName="navigateMoreKeysStyle"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
+                latin:moreKeys="!fixedColumnOrder!2,\@string/action_previous_as_more_key,\@string/action_next_as_more_key" />
+        </case>
+        <case
+            latin:navigateNext="true"
+            latin:navigatePrevious="false"
+        >
+            <key-style
+                latin:styleName="navigateMoreKeysStyle"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
+                latin:moreKeys="@string/action_next_as_more_key" />
+        </case>
+        <case
+            latin:navigateNext="false"
+            latin:navigatePrevious="true"
+        >
+            <key-style
+                latin:styleName="navigateMoreKeysStyle"
+                latin:keyLabelFlags="hasPopupHint|preserveCase"
+                latin:moreKeys="@string/action_previous_as_more_key" />
+        </case>
+        <!-- naviagteNext="false" and navigatePrevious="false" -->
+        <default>
+            <key-style
+                latin:styleName="navigateMoreKeysStyle" />
+        </default>
+    </switch>
     <!-- Enter key style -->
     <key-style
         latin:styleName="defaultEnterKeyStyle"
@@ -28,7 +82,8 @@
         latin:keyIcon="iconReturnKey"
         latin:keyLabelFlags="autoXScale|preserveCase"
         latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
+        latin:backgroundType="functional"
+        latin:parentStyle="navigateMoreKeysStyle" />
     <key-style
         latin:styleName="defaultActionKeyStyle"
         latin:code="@integer/key_action_enter"
@@ -45,18 +100,6 @@
                 latin:styleName="enterKeyStyle"
                 latin:parentStyle="defaultEnterKeyStyle" />
         </case>
-        <!-- Smiley in textShortMessage field. -->
-        <case
-            latin:mode="im"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel=":-)"
-                latin:keyOutputText=":-) "
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="@string/more_keys_for_smiley"
-                latin:backgroundType="functional" />
-        </case>
         <case
             latin:imeAction="actionGo"
         >
diff --git a/java/res/xml/key_styles_enter_tablet.xml b/java/res/xml/key_styles_enter_tablet.xml
deleted file mode 100644
index 7020891..0000000
--- a/java/res/xml/key_styles_enter_tablet.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <!-- Enter key style -->
-    <key-style
-        latin:styleName="defaultEnterKeyStyle"
-        latin:code="@integer/key_enter"
-        latin:keyIcon="iconReturnKey"
-        latin:keyLabelFlags="autoXScale|preserveCase"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
-    <key-style
-        latin:styleName="defaultActionKeyStyle"
-        latin:code="@integer/key_action_enter"
-        latin:keyIcon="iconUndefined"
-        latin:backgroundType="action"
-        latin:parentStyle="defaultEnterKeyStyle" />
-    <switch>
-        <!-- Shift + Enter in textMultiLine field. -->
-        <case
-            latin:isMultiLine="true"
-            latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:parentStyle="defaultEnterKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionGo"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel="@string/label_go_key"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionNext"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel="@string/label_next_key"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionPrevious"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel="@string/label_previous_key"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionDone"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel="@string/label_done_key"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionSend"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabel="@string/label_send_key"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionSearch"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyIcon="iconSearchKey"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <case
-            latin:imeAction="actionCustomLabel"
-        >
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:keyLabelFlags="fromCustomActionLabel"
-                latin:parentStyle="defaultActionKeyStyle" />
-        </case>
-        <!-- imeAction is either actionNone or actionUnspecified. -->
-        <default>
-            <key-style
-                latin:styleName="enterKeyStyle"
-                latin:parentStyle="defaultEnterKeyStyle" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/key_symbols_f1.xml b/java/res/xml/key_symbols_f1.xml
deleted file mode 100644
index ac4031f..0000000
--- a/java/res/xml/key_symbols_f1.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <switch>
-        <case
-            latin:navigateAction="false"
-        >
-            <switch>
-                <case
-                    latin:hasShortcutKey="true"
-                >
-                    <Key
-                        latin:keyStyle="shortcutKeyStyle" />
-                </case>
-                <!-- latin:hasShortcutKey="false" -->
-                <default>
-                    <Key
-                        latin:keyLabel="@string/keylabel_for_comma"
-                        latin:keyLabelFlags="hasPopupHint"
-                        latin:additionalMoreKeys="@string/more_keys_for_comma"
-                        latin:keyStyle="f1PopupStyle" />
-                </default>
-            </switch>
-        </case>
-        <!-- navigateAction="true" -->
-        <default>
-            <switch>
-                <case
-                    latin:hasShortcutKey="true"
-                >
-                    <Key
-                        latin:keyStyle="shortcutKeyStyle"
-                        latin:keyWidth="9.2%p" />
-                </case>
-                <!-- latin:hasShortcutKey="false" -->
-                <default>
-                    <Key
-                        latin:keyLabel="@string/keylabel_for_comma"
-                        latin:keyLabelFlags="hasPopupHint"
-                        latin:additionalMoreKeys="@string/more_keys_for_comma"
-                        latin:keyStyle="f1PopupStyle"
-                        latin:keyWidth="9.2%p" />
-                    </default>
-            </switch>
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 650f91b..98dc766 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -21,7 +21,7 @@
 <!-- for the Input Method Manager. -->
 
 <!-- Keyboard: en_US, en_GB, ar, be, bg, cs, da, de, de(QWERTY), es, es_US, et, fi, fr, fr_CA,
-     fr_CH, hr, hu, it, iw, ky, lt, lv, nb, nl, pl, pt, ro, ru, sk, sl, sr, sv, tr, uk, vi -->
+     fr_CH, hr, hu, it, iw, ka, ky, lt, lv, nb, nl, pl, pt, ro, ru, sk, sl, sr, sv, tr, uk, vi -->
 <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. -->
 <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default
      subtype.-->
@@ -145,6 +145,12 @@
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
+            android:imeSubtypeLocale="ka"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
+    />
+    <subtype android:icon="@drawable/ic_subtype_keyboard"
+            android:label="@string/subtype_generic"
             android:imeSubtypeLocale="ky"
             android:imeSubtypeMode="keyboard"
             android:imeSubtypeExtraValue="SupportTouchPositionCorrection"
diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml
index 2f8b82c..df9c8fe 100644
--- a/java/res/xml/row_qwerty4.xml
+++ b/java/res/xml/row_qwerty4.xml
@@ -24,44 +24,46 @@
     <Row
         latin:keyWidth="10%p"
     >
+        <Key
+            latin:keyStyle="toSymbolKeyStyle"
+            latin:keyWidth="15%p" />
         <switch>
             <case
-                latin:navigateAction="false"
+                latin:mode="url"
             >
                 <Key
-                    latin:keyStyle="toSymbolKeyStyle"
-                    latin:keyWidth="15%p" />
-                <include
-                    latin:keyboardLayout="@xml/key_f1" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="50%p" />
-                <Key
-                    latin:keyStyle="punctuationKeyStyle" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
+                    latin:keyLabel="/"
+                    latin:keyStyle="f1MoreKeysStyle" />
             </case>
-            <!-- TODO: Remove dedicated navigation tab key. -->
-            <!-- navigateAction="true" -->
+            <case
+                latin:mode="email"
+            >
+                <Key
+                    latin:keyLabel="\@"
+                    latin:keyStyle="f1MoreKeysStyle" />
+            </case>
+            <case
+                latin:hasShortcutKey="true"
+            >
+                <Key
+                    latin:keyStyle="shortcutKeyStyle" />
+            </case>
+            <!-- latin:hasShortcutKey="false" -->
             <default>
                 <Key
-                    latin:keyStyle="toSymbolKeyStyle"
-                    latin:keyWidth="13.75%p" />
-                <include
-                    latin:keyboardLayout="@xml/key_navigation_tab" />
-                <include
-                    latin:keyboardLayout="@xml/key_f1" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="35.83%p" />
-                <Key
-                    latin:keyStyle="punctuationKeyStyle"
-                    latin:keyWidth="9.2%p" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
+                    latin:keyLabel="@string/keylabel_for_comma"
+                    latin:keyLabelFlags="hasPopupHint"
+                    latin:additionalMoreKeys="@string/more_keys_for_comma"
+                    latin:keyStyle="f1MoreKeysStyle" />
             </default>
         </switch>
+        <Key
+            latin:keyStyle="spaceKeyStyle"
+            latin:keyWidth="50%p" />
+        <Key
+            latin:keyStyle="punctuationKeyStyle" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
     </Row>
 </merge>
diff --git a/java/res/xml/row_symbols4.xml b/java/res/xml/row_symbols4.xml
deleted file mode 100644
index ef77bc3..0000000
--- a/java/res/xml/row_symbols4.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <Row
-        latin:keyWidth="10%p"
-    >
-        <switch>
-            <case
-                latin:navigateAction="false"
-            >
-                <Key
-                    latin:keyStyle="toAlphaKeyStyle"
-                    latin:keyWidth="15%p" />
-                <include
-                    latin:keyboardLayout="@xml/key_symbols_f1" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="50%p" />
-                <Key
-                    latin:keyStyle="punctuationKeyStyle" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </case>
-            <!-- TODO: Remove dedicated navigation tab key. -->
-            <!-- navigateAction="true" -->
-            <default>
-                <Key
-                    latin:keyStyle="toAlphaKeyStyle"
-                    latin:keyWidth="13.75%p" />
-                <include
-                    latin:keyboardLayout="@xml/key_navigation_tab" />
-                <include
-                    latin:keyboardLayout="@xml/key_f1" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="35.83%p" />
-                <Key
-                    latin:keyStyle="punctuationKeyStyle"
-                    latin:keyWidth="9.2%p" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </default>
-        </switch>
-    </Row>
-</merge>
diff --git a/java/res/xml/row_symbols_shift4.xml b/java/res/xml/row_symbols_shift4.xml
deleted file mode 100644
index 632aafc..0000000
--- a/java/res/xml/row_symbols_shift4.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2010, 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.
-*/
--->
-
-<merge
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
->
-    <Row
-        latin:keyWidth="10%p"
-    >
-        <switch>
-            <case
-                latin:navigateAction="false"
-            >
-                <Key
-                    latin:keyStyle="toAlphaKeyStyle"
-                    latin:keyWidth="15%p" />
-                <!-- U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
-                <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
-                    <!-- latin:keyLabelFlags="hasPopupHint" -->
-                    <!-- latin:moreKeys="&#x201F;" -->
-                <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
-                <Key
-                    latin:keyLabel="&#x201E;"
-                    latin:backgroundType="functional" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="50%p" />
-                <!-- U+2026: "…" HORIZONTAL ELLIPSIS -->
-                <Key
-                    latin:keyLabel="&#x2026;"
-                    latin:backgroundType="functional" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </case>
-            <!-- TODO: Remove dedicated navigation tab key. -->
-            <!-- navigateAction="true" -->
-            <default>
-                <Key
-                    latin:keyStyle="toAlphaKeyStyle"
-                    latin:keyWidth="13.75%p" />
-                <include
-                    latin:keyboardLayout="@xml/key_navigation_tab" />
-                <!-- U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
-                <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
-                    <!-- latin:keyLabelFlags="hasPopupHint" -->
-                    <!-- latin:moreKeys="&#x201F;" -->
-                <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
-                <Key
-                    latin:keyLabel="&#x201E;"
-                    latin:keyWidth="9.2%p"
-                    latin:backgroundType="functional" />
-                <Key
-                    latin:keyStyle="spaceKeyStyle"
-                    latin:keyWidth="35.83%p" />
-                <!-- U+2026: "…" HORIZONTAL ELLIPSIS -->
-                <Key
-                    latin:keyLabel="&#x2026;"
-                    latin:keyWidth="9.2%p"
-                    latin:backgroundType="functional" />
-                <Key
-                    latin:keyStyle="enterKeyStyle"
-                    latin:keyWidth="fillRight" />
-            </default>
-        </switch>
-    </Row>
-</merge>
diff --git a/java/res/xml/rows_georgian.xml b/java/res/xml/rows_georgian.xml
new file mode 100644
index 0000000..d7d66a3
--- /dev/null
+++ b/java/res/xml/rows_georgian.xml
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="Q"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="1"
+                    latin:additionalMoreKeys="1" />
+                <!-- U+10ED: "ჭ" GEORGIAN LETTER CHAR -->
+                <Key
+                    latin:keyLabel="&#x10ED;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="2"
+                    latin:additionalMoreKeys="2" />
+                <Key
+                    latin:keyLabel="E"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="3"
+                    latin:additionalMoreKeys="3" />
+                <!-- U+10E6: "ღ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E6;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="4"
+                    latin:additionalMoreKeys="4" />
+                <!-- U+10D7: "თ" GEORGIAN LETTER TAN -->
+                <Key
+                    latin:keyLabel="&#x10D7;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="5"
+                    latin:additionalMoreKeys="5" />
+                <Key
+                    latin:keyLabel="Y"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="6"
+                    latin:additionalMoreKeys="6" />
+                <Key
+                    latin:keyLabel="U"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="7"
+                    latin:additionalMoreKeys="7" />
+                <Key
+                    latin:keyLabel="I"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="8"
+                    latin:additionalMoreKeys="8" />
+                <Key
+                    latin:keyLabel="O"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="9"
+                    latin:additionalMoreKeys="9" />
+                <Key
+                    latin:keyLabel="P"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="0"
+                    latin:additionalMoreKeys="0"
+                    latin:keyWidth="fillRight" />
+            </case>
+            <default>
+                <!-- U+10E5: "ქ" GEORGIAN LETTER GHAN -->
+                <Key
+                    latin:keyLabel="&#x10E5;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="1"
+                    latin:additionalMoreKeys="1" />
+                <!-- U+10EC: "წ" GEORGIAN LETTER CIL -->
+                <Key
+                    latin:keyLabel="&#x10EC;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="2"
+                    latin:additionalMoreKeys="2" />
+                <!-- U+10D4: "ე" GEORGIAN LETTER EN
+                     U+10F1: "ჱ" GEORGIAN LETTER HE -->
+                <Key
+                    latin:keyLabel="&#x10D4;"
+                    latin:moreKeys="&#x10F1;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="3"
+                    latin:additionalMoreKeys="3" />
+                <!-- U+10E0: "რ" GEORGIAN LETTER RAE -->
+                <Key
+                    latin:keyLabel="&#x10E0;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="4"
+                    latin:additionalMoreKeys="4" />
+                <!-- U+10E2: "ტ" GEORGIAN LETTER TAR -->
+                <Key
+                    latin:keyLabel="&#x10E2;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="5"
+                    latin:additionalMoreKeys="5" />
+                <!-- U+10E7: "ყ" GEORGIAN LETTER QAR
+                     U+10F8: "ჸ" GEORGIAN LETTER ELIFI -->
+                <Key
+                    latin:keyLabel="&#x10E7;"
+                    latin:moreKeys="&#x10F8;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="6"
+                    latin:additionalMoreKeys="6" />
+                <!-- U+10E3: "უ" GEORGIAN LETTER UN -->
+                <Key
+                    latin:keyLabel="&#x10E3;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="7"
+                    latin:additionalMoreKeys="7" />
+                <!-- U+10D8: "ი" GEORGIAN LETTER IN
+                     U+10F2: "ჲ" GEORGIAN LETTER HIE -->
+                <Key
+                    latin:keyLabel="&#x10D8;"
+                    latin:moreKeys="&#x10F2;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="8"
+                    latin:additionalMoreKeys="8" />
+                <!-- U+10DD: "ო" GEORGIAN LETTER ON -->
+                <Key
+                    latin:keyLabel="&#x10DD;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="9"
+                    latin:additionalMoreKeys="9" />
+                <!-- U+10DE: "პ" GEORGIAN LETTER PAR -->
+                <Key
+                    latin:keyLabel="&#x10DE;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyHintLabel="0"
+                    latin:additionalMoreKeys="0"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <Key
+                    latin:keyLabel="A"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyXPos="5%p" />
+                <!-- U+10E8: "შ" GEORGIAN LETTER SHIN -->
+                <Key
+                    latin:keyLabel="&#x10E8;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="D"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="F"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="G"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="H"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DF: "ჟ" GEORGIAN LETTER ZHAR -->
+                <Key
+                    latin:keyLabel="&#x10DF;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="K"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="L"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D0: "ა" GEORGIAN LETTER AN
+                     U+10FA: "ჺ" GEORGIAN LETTER AIN -->
+                <Key
+                    latin:keyLabel="&#x10D0;"
+                    latin:moreKeys="&#x10FA;"
+                    latin:keyLabelFlags="preserveCase"
+                    latin:keyXPos="5%p" />
+                <!-- U+10E1: "ს" GEORGIAN LETTER SAN -->
+                <Key
+                    latin:keyLabel="&#x10E1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D3: "დ" GEORGIAN LETTER DON -->
+                <Key
+                    latin:keyLabel="&#x10D3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E4: "ფ" GEORGIAN LETTER PHAR
+                     U+10F6: "ჶ" GEORGIAN LETTER FI -->
+                <Key
+                    latin:keyLabel="&#x10E4;"
+                    latin:moreKeys="&#x10F6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D2: "გ" GEORGIAN LETTER GAN
+                     U+10F9: "ჹ" GEORGIAN LETTER TURNED GAN -->
+                <Key
+                    latin:keyLabel="&#x10D2;"
+                    latin:moreKeys="&#x10F9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10F0: "ჰ" GEORGIAN LETTER HAE
+                     U+10F5: "ჵ" GEORGIAN LETTER HOE -->
+                <Key
+                    latin:keyLabel="&#x10F0;"
+                    latin:moreKeys="&#x10F5;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EF: "ჯ" GEORGIAN LETTER JHAN
+                     U+10F7: "ჷ" GEORGIAN LETTER YN -->
+                <Key
+                    latin:keyLabel="&#x10EF;"
+                    latin:moreKeys="&#x10F7;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D9: "კ" GEORGIAN LETTER KAN -->
+                <Key
+                    latin:keyLabel="&#x10D9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DA: "ლ" GEORGIAN LETTER LAS -->
+                <Key
+                    latin:keyLabel="&#x10DA;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <!-- Here is 5%p space -->
+    </Row>
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="15%p"
+            latin:visualInsetsRight="1%p" />
+        <switch>
+            <case
+                latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+            >
+                <!-- U+10EB: "ძ" GEORGIAN LETTER JIL -->
+                <Key
+                    latin:keyLabel="&#x10EB;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="X"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10E9: "ჩ" GEORGIAN LETTER CHIN -->
+                <Key
+                    latin:keyLabel="&#x10E9;"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="V"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="B"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="N"
+                    latin:keyLabelFlags="preserveCase" />
+                <Key
+                    latin:keyLabel="M"
+                    latin:keyLabelFlags="preserveCase" />
+            </case>
+            <default>
+                <!-- U+10D6: "ზ" GEORGIAN LETTER ZEN -->
+                <Key
+                    latin:keyLabel="&#x10D6;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EE: "ხ" GEORGIAN LETTER XAN
+                     U+10F4: "ჴ" GEORGIAN LETTER HAR -->
+                <Key
+                    latin:keyLabel="&#x10EE;"
+                    latin:moreKeys="&#x10F4;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10EA: "ც" GEORGIAN LETTER CAN -->
+                <Key
+                    latin:keyLabel="&#x10EA;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D5: "ვ" GEORGIAN LETTER VIN
+                     U+10F3: "ჳ" GEORGIAN LETTER WE -->
+                <Key
+                    latin:keyLabel="&#x10D5;"
+                    latin:moreKeys="&#x10F3;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10D1: "ბ" GEORGIAN LETTER BAN -->
+                <Key
+                    latin:keyLabel="&#x10D1;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DC: "ნ" GEORGIAN LETTER NAR
+                     U+10FC: "ჼ" MODIFIER LETTER GEORGIAN NAR -->
+                <Key
+                    latin:keyLabel="&#x10DC;"
+                    latin:moreKeys="&#x10FC;"
+                    latin:keyLabelFlags="preserveCase" />
+                <!-- U+10DB: "მ" GEORGIAN LETTER MAN -->
+                <Key
+                    latin:keyLabel="&#x10DB;"
+                    latin:keyLabelFlags="preserveCase" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillBoth"
+            latin:visualInsetsLeft="1%p" />
+    </Row>
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_symbols.xml b/java/res/xml/rows_symbols.xml
index 27f75b5..21f7d1d 100644
--- a/java/res/xml/rows_symbols.xml
+++ b/java/res/xml/rows_symbols.xml
@@ -128,6 +128,35 @@
             latin:keyWidth="fillRight"
             latin:visualInsetsLeft="1%p" />
     </Row>
-    <include
-        latin:keyboardLayout="@xml/row_symbols4" />
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <Key
+            latin:keyStyle="toAlphaKeyStyle"
+            latin:keyWidth="15%p" />
+        <switch>
+            <case
+                latin:hasShortcutKey="true"
+            >
+                <Key
+                    latin:keyStyle="shortcutKeyStyle" />
+            </case>
+            <!-- latin:hasShortcutKey="false" -->
+            <default>
+                <Key
+                    latin:keyLabel="@string/keylabel_for_comma"
+                    latin:keyLabelFlags="hasPopupHint"
+                    latin:additionalMoreKeys="@string/more_keys_for_comma"
+                    latin:keyStyle="f1MoreKeysStyle" />
+            </default>
+        </switch>
+        <Key
+            latin:keyStyle="spaceKeyStyle"
+            latin:keyWidth="50%p" />
+        <Key
+            latin:keyStyle="punctuationKeyStyle" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
 </merge>
diff --git a/java/res/xml/rows_symbols_shift.xml b/java/res/xml/rows_symbols_shift.xml
index 3fb8214..a7d0499 100644
--- a/java/res/xml/rows_symbols_shift.xml
+++ b/java/res/xml/rows_symbols_shift.xml
@@ -119,6 +119,29 @@
             latin:keyWidth="fillRight"
             latin:visualInsetsLeft="1%p" />
     </Row>
-    <include
-        latin:keyboardLayout="@xml/row_symbols_shift4" />
+    <Row
+        latin:keyWidth="10%p"
+    >
+        <Key
+            latin:keyStyle="toAlphaKeyStyle"
+            latin:keyWidth="15%p" />
+        <!-- U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK -->
+        <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. -->
+        <!-- latin:keyLabelFlags="hasPopupHint" -->
+        <!-- latin:moreKeys="&#x201F;" -->
+        <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK -->
+        <Key
+            latin:keyLabel="&#x201E;"
+            latin:backgroundType="functional" />
+        <Key
+            latin:keyStyle="spaceKeyStyle"
+            latin:keyWidth="50%p" />
+        <!-- U+2026: "…" HORIZONTAL ELLIPSIS -->
+        <Key
+            latin:keyLabel="&#x2026;"
+            latin:backgroundType="functional" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
 </merge>
diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
index 3247997..938388d 100644
--- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java
@@ -39,30 +39,30 @@
     private static final Integer OBJ_IME_ACTION_PREVIOUS = (Integer) CompatUtils
             .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS);
 
+    // EditorInfo.IME_FLAG_NAVIGATE_NEXT has been introduced since API#11 (Honeycomb).
     public static boolean hasFlagNavigateNext(int imeOptions) {
         if (OBJ_IME_FLAG_NAVIGATE_NEXT == null)
             return false;
         return (imeOptions & OBJ_IME_FLAG_NAVIGATE_NEXT) != 0;
     }
 
+    // EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS has been introduced since API#11 (Honeycomb).
     public static boolean hasFlagNavigatePrevious(int imeOptions) {
         if (OBJ_IME_FLAG_NAVIGATE_PREVIOUS == null)
             return false;
         return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0;
     }
 
+    // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean).
     public static boolean hasFlagForceAscii(int imeOptions) {
         if (OBJ_IME_FLAG_FORCE_ASCII == null)
             return false;
         return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0;
     }
 
-    public static void performEditorActionNext(InputConnection ic) {
-        ic.performEditorAction(EditorInfo.IME_ACTION_NEXT);
-    }
-
+    // EditorInfo.IME_ACTION_PREVIOUS has been introduced since API#11 (Honeycomb).
     public static void performEditorActionPrevious(InputConnection ic) {
-        if (OBJ_IME_ACTION_PREVIOUS == null)
+        if (OBJ_IME_ACTION_PREVIOUS == null || ic == null)
             return;
         ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS);
     }
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
index f632b0e..5c4e9af 100644
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
@@ -56,6 +56,7 @@
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.LatinKeyboardView;
 import com.android.inputmethod.latin.EditingUtils;
+import com.android.inputmethod.latin.LastComposedWord;
 import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.LatinIME.UIHandler;
 import com.android.inputmethod.latin.LatinImeLogger;
@@ -553,7 +554,7 @@
         mHints.registerVoiceResult(bestResult);
 
         if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
-        mService.commitTyped(ic);
+        mService.commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
         EditingUtils.appendText(ic, bestResult);
         if (ic != null) ic.endBatchEdit();
 
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 60e5069..30ed59e 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -99,8 +99,10 @@
     public static final int CODE_SETTINGS = -5;
     public static final int CODE_SHORTCUT = -6;
     public static final int CODE_ACTION_ENTER = -7;
+    public static final int CODE_ACTION_NEXT = -8;
+    public static final int CODE_ACTION_PREVIOUS = -9;
     // Code value representing the code is not specified.
-    public static final int CODE_UNSPECIFIED = -9;
+    public static final int CODE_UNSPECIFIED = -10;
 
     public final KeyboardId mId;
     public final int mThemeId;
@@ -381,6 +383,8 @@
         case CODE_SETTINGS: return "settings";
         case CODE_SHORTCUT: return "shortcut";
         case CODE_ACTION_ENTER: return "actionEnter";
+        case CODE_ACTION_NEXT: return "actionNext";
+        case CODE_ACTION_PREVIOUS: return "actionPrevious";
         case CODE_UNSPECIFIED: return "unspec";
         case CODE_TAB: return "tab";
         case CODE_ENTER: return "enter";
@@ -1069,8 +1073,10 @@
                         KeyboardId.elementIdToName(id.mElementId));
                 final boolean modeMatched = matchTypedValue(a,
                         R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
-                final boolean navigateActionMatched = matchBoolean(a,
-                        R.styleable.Keyboard_Case_navigateAction, id.navigateAction());
+                final boolean navigateNextMatched = matchBoolean(a,
+                        R.styleable.Keyboard_Case_navigateNext, id.navigateNext());
+                final boolean navigatePreviousMatched = matchBoolean(a,
+                        R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious());
                 final boolean passwordInputMatched = matchBoolean(a,
                         R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
                 final boolean clobberSettingsKeyMatched = matchBoolean(a,
@@ -1090,30 +1096,32 @@
                 final boolean countryCodeMatched = matchString(a,
                         R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
                 final boolean selected = keyboardSetElementMatched && modeMatched
-                        && navigateActionMatched && passwordInputMatched
+                        && navigateNextMatched && navigatePreviousMatched && passwordInputMatched
                         && clobberSettingsKeyMatched && shortcutKeyEnabledMatched
                         && hasShortcutKeyMatched && isMultiLineMatched && imeActionMatched
                         && localeCodeMatched && languageCodeMatched && countryCodeMatched;
 
                 if (DEBUG) {
-                    startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
+                    startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
                             textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement),
                                     "keyboardSetElement"),
                             textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
-                            booleanAttr(a, R.styleable.Keyboard_Case_navigateAction,
-                                    "navigateAction"),
-                            booleanAttr(a, R.styleable.Keyboard_Case_passwordInput,
-                                    "passwordInput"),
+                            textAttr(a.getString(R.styleable.Keyboard_Case_imeAction),
+                                    "imeAction"),
+                            booleanAttr(a, R.styleable.Keyboard_Case_navigateNext,
+                                    "navigateNext"),
+                            booleanAttr(a, R.styleable.Keyboard_Case_navigatePrevious,
+                                    "navigatePrevious"),
                             booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
                                     "clobberSettingsKey"),
+                            booleanAttr(a, R.styleable.Keyboard_Case_passwordInput,
+                                    "passwordInput"),
                             booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled,
                                     "shortcutKeyEnabled"),
                             booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey,
                                     "hasShortcutKey"),
                             booleanAttr(a, R.styleable.Keyboard_Case_isMultiLine,
                                     "isMultiLine"),
-                            textAttr(a.getString(R.styleable.Keyboard_Case_imeAction),
-                                    "imeAction"),
                             textAttr(a.getString(R.styleable.Keyboard_Case_localeCode),
                                     "localeCode"),
                             textAttr(a.getString(R.styleable.Keyboard_Case_languageCode),
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index a75caf2..ed4a89e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -87,7 +87,6 @@
                 id.mElementId,
                 id.mMode,
                 id.mWidth,
-                id.navigateAction(),
                 id.passwordInput(),
                 id.mClobberSettingsKey,
                 id.mShortcutKeyEnabled,
@@ -95,6 +94,8 @@
                 id.isMultiLine(),
                 id.imeAction(),
                 id.mCustomActionLabel,
+                id.navigateNext(),
+                id.navigatePrevious(),
                 id.mLocale
         });
     }
@@ -106,7 +107,6 @@
                 && other.mElementId == this.mElementId
                 && other.mMode == this.mMode
                 && other.mWidth == this.mWidth
-                && other.navigateAction() == this.navigateAction()
                 && other.passwordInput() == this.passwordInput()
                 && other.mClobberSettingsKey == this.mClobberSettingsKey
                 && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
@@ -114,6 +114,8 @@
                 && other.isMultiLine() == this.isMultiLine()
                 && other.imeAction() == this.imeAction()
                 && TextUtils.equals(other.mCustomActionLabel, this.mCustomActionLabel)
+                && other.navigateNext() == this.navigateNext()
+                && other.navigatePrevious() == this.navigatePrevious()
                 && other.mLocale.equals(this.mLocale);
     }
 
@@ -146,12 +148,12 @@
         return mElementId == ELEMENT_PHONE_SYMBOLS;
     }
 
-    public boolean navigateAction() {
-        // Note: Turn off checking navigation flag to show TAB key for now.
-        boolean navigateAction = InputTypeCompatUtils.isWebInputType(mEditorInfo.inputType);
-//                || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
-//                || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
-        return navigateAction;
+    public boolean navigateNext() {
+        return EditorInfoCompatUtils.hasFlagNavigateNext(mEditorInfo.imeOptions);
+    }
+
+    public boolean navigatePrevious() {
+        return EditorInfoCompatUtils.hasFlagNavigatePrevious(mEditorInfo.imeOptions);
     }
 
     public boolean passwordInput() {
@@ -165,15 +167,21 @@
     }
 
     public int imeAction() {
+        final int actionId = mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
         if ((mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
             return EditorInfo.IME_ACTION_NONE;
         } else if (mEditorInfo.actionLabel != null) {
             return IME_ACTION_CUSTOM_LABEL;
         } else {
-            return mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
+            return actionId;
         }
     }
 
+    public int imeActionId() {
+        final int actionId = imeAction();
+        return actionId == IME_ACTION_CUSTOM_LABEL ? mEditorInfo.actionId : actionId;
+    }
+
     @Override
     public boolean equals(Object other) {
         return other instanceof KeyboardId && equals((KeyboardId) other);
@@ -186,17 +194,19 @@
 
     @Override
     public String toString() {
-        return String.format("[%s %s %s%d %s %s %s%s%s%s%s]",
+        return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]",
                 elementIdToName(mElementId),
                 mLocale,
                 (mOrientation == 1 ? "port" : "land"), mWidth,
                 modeName(mMode),
                 imeAction(),
+                (navigateNext() ? "navigateNext" : ""),
+                (navigatePrevious() ? "navigatePrevious" : ""),
                 (mClobberSettingsKey ? " clobberSettingsKey" : ""),
-                (navigateAction() ? " navigateAction" : ""),
                 (passwordInput() ? " passwordInput" : ""),
                 (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""),
-                (mHasShortcutKey ? " hasShortcutKey" : "")
+                (mHasShortcutKey ? " hasShortcutKey" : ""),
+                (isMultiLine() ? "isMultiLine" : "")
         );
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 12a9c51..9e5c227 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -163,10 +163,10 @@
         if (DEBUG) {
             Log.d(TAG, String.format("<%s styleName=%s />",
                     Keyboard.Builder.TAG_KEY_STYLE, styleName));
-        }
-        if (mStyles.containsKey(styleName)) {
-            throw new XmlParseUtils.ParseException(
-                    "duplicate key style declared: " + styleName, parser);
+            if (mStyles.containsKey(styleName)) {
+                Log.d(TAG, "key-style " + styleName + " is overridden at "
+                        + parser.getPositionDescription());
+            }
         }
 
         final DeclaredKeyStyle style = new DeclaredKeyStyle();
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index f34cb5f..bc07924 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -40,26 +40,31 @@
     // an auto-correction.
     public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3;
 
+    public static final int NOT_A_SEPARATOR = -1;
+
     public final ArrayList<int[]> mCodes;
     public final int[] mXCoordinates;
     public final int[] mYCoordinates;
     public final String mTypedWord;
-    public final String mAutoCorrection;
+    public final String mCommittedWord;
+    public final int mSeparatorCode;
 
     private boolean mActive;
 
     public static final LastComposedWord NOT_A_COMPOSED_WORD =
-            new LastComposedWord(null, null, null, "", "");
+            new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR);
 
     // Warning: this is using the passed objects as is and fully expects them to be
     // immutable. Do not fiddle with their contents after you passed them to this constructor.
     public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates,
-            final int[] yCoordinates, final String typedWord, final String autoCorrection) {
+            final int[] yCoordinates, final String typedWord, final String committedWord,
+            final int separatorCode) {
         mCodes = codes;
         mXCoordinates = xCoordinates;
         mYCoordinates = yCoordinates;
         mTypedWord = typedWord;
-        mAutoCorrection = autoCorrection;
+        mCommittedWord = committedWord;
+        mSeparatorCode = separatorCode;
         mActive = true;
     }
 
@@ -67,8 +72,15 @@
         mActive = false;
     }
 
-    public boolean canCancelAutoCorrect() {
-        return mActive && !TextUtils.isEmpty(mAutoCorrection)
-                && !TextUtils.equals(mTypedWord, mAutoCorrection);
+    public boolean canRevertCommit() {
+        return mActive && !TextUtils.isEmpty(mCommittedWord);
+    }
+
+    public boolean didCommitTypedWord() {
+        return TextUtils.equals(mTypedWord, mCommittedWord);
+    }
+
+    public static int getSeparatorLength(final int separatorCode) {
+        return NOT_A_SEPARATOR == separatorCode ? 0 : 1;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ce306ea..47ec40f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -165,8 +165,8 @@
     // Double space: the state where the user pressed space twice quickly, which LatinIME
     // resolved as period-space. Undoing this converts the period to a space.
     private static final int SPACE_STATE_DOUBLE = 1;
-    // Swap punctuation: the state where a (weak or magic) space and a punctuation from the
-    // suggestion strip have just been swapped. Undoing this swaps them back.
+    // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip
+    // have just been swapped. Undoing this swaps them back; the space is still considered weak.
     private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
     // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
     // spaces happen when the user presses space, accepting the current suggestion (whether
@@ -658,7 +658,7 @@
             mDisplayOrientation = conf.orientation;
             mHandler.startOrientationChanging();
             final InputConnection ic = getCurrentInputConnection();
-            commitTyped(ic);
+            commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
             if (ic != null) ic.finishComposingText(); // For voice input
             if (isShowingOptionDialog())
                 mOptionsDialog.dismiss();
@@ -887,26 +887,16 @@
             // the second one - the first call successfully avoids this test, but the second one
             // enters. For the moment we rely on noComposingSpan to further reduce the impact.
 
+            // TODO: the following is probably better done in resetEntireInputState().
+            // it should only happen when the cursor moved, and the very purpose of the
+            // test below is to narrow down whether this happened or not. Likewise with
+            // the call to postUpdateShiftState.
             // We set this to NONE because after a cursor move, we don't want the space
             // state-related special processing to kick in.
             mSpaceState = SPACE_STATE_NONE;
 
-            if (((mWordComposer.isComposingWord())
-                    || mVoiceProxy.isVoiceInputHighlighted())
-                    && (selectionChanged || noComposingSpan)) {
-                resetComposingState(true /* alsoResetLastComposedWord */);
-                updateSuggestions();
-                final InputConnection ic = getCurrentInputConnection();
-                if (ic != null) {
-                    ic.finishComposingText();
-                }
-                mComposingStateManager.onFinishComposingText();
-                mVoiceProxy.setVoiceInputHighlighted(false);
-            } else if (!mWordComposer.isComposingWord()) {
-                // TODO: is the following reset still needed, given that we are not composing
-                // a word?
-                resetComposingState(true /* alsoResetLastComposedWord */);
-                updateSuggestions();
+            if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) {
+                resetEntireInputState();
             }
 
             mHandler.postUpdateShiftState();
@@ -1116,17 +1106,33 @@
         return super.onKeyUp(keyCode, event);
     }
 
+    // This will reset the whole input state to the starting state. It will clear
+    // the composing word, reset the last composed word, tell the inputconnection
+    // and the composingStateManager about it.
+    private void resetEntireInputState() {
+        resetComposingState(true /* alsoResetLastComposedWord */);
+        updateSuggestions();
+        final InputConnection ic = getCurrentInputConnection();
+        if (ic != null) {
+            ic.finishComposingText();
+        }
+        mComposingStateManager.onFinishComposingText();
+        mVoiceProxy.setVoiceInputHighlighted(false);
+    }
+
     private void resetComposingState(final boolean alsoResetLastComposedWord) {
         mWordComposer.reset();
         if (alsoResetLastComposedWord)
             mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
     }
 
-    public void commitTyped(final InputConnection ic) {
+    public void commitTyped(final InputConnection ic, final int separatorCode) {
         if (!mWordComposer.isComposingWord()) return;
         final CharSequence typedWord = mWordComposer.getTypedWord();
-        mLastComposedWord = mWordComposer.commitWord(LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD);
         if (typedWord.length() > 0) {
+            mLastComposedWord = mWordComposer.commitWord(
+                    LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
+                    separatorCode);
             if (ic != null) {
                 ic.commitText(typedWord, 1);
             }
@@ -1242,11 +1248,8 @@
                 KeyboardActionListener.SUGGESTION_STRIP_COORDINATE);
     }
 
-    private static int getEditorActionId(EditorInfo editorInfo) {
-        if (editorInfo == null) return 0;
-        return (editorInfo.actionLabel != null)
-                ? editorInfo.actionId
-                : (editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION);
+    private static int getActionId(Keyboard keyboard) {
+        return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE;
     }
 
     private void performeEditorAction(int actionId) {
@@ -1312,18 +1315,13 @@
             mSubtypeSwitcher.switchToShortcutIME();
             break;
         case Keyboard.CODE_ACTION_ENTER:
-            performeEditorAction(getEditorActionId(getCurrentInputEditorInfo()));
+            performeEditorAction(getActionId(switcher.getKeyboard()));
             break;
-        case Keyboard.CODE_TAB:
-            handleTab();
-            // There are two cases for tab. Either we send a "next" event, that may change the
-            // focus but will never move the cursor. Or, we send a real tab keycode, which some
-            // applications may accept or ignore, and we don't know whether this will move the
-            // cursor or not. So actually, we don't really know.
-            // So to go with the safer option, we'd rather behave as if the user moved the
-            // cursor when they didn't than the opposite. We also expect that most applications
-            // will actually use tab only for focus movement.
-            // To sum it up: do not update mExpectingUpdateSelection here.
+        case Keyboard.CODE_ACTION_NEXT:
+            performeEditorAction(EditorInfo.IME_ACTION_NEXT);
+            break;
+        case Keyboard.CODE_ACTION_PREVIOUS:
+            EditorInfoCompatUtils.performEditorActionPrevious(getCurrentInputConnection());
             break;
         default:
             mSpaceState = SPACE_STATE_NONE;
@@ -1348,7 +1346,7 @@
         final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return;
         ic.beginBatchEdit();
-        commitTyped(ic);
+        commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR);
         text = specificTldProcessingOnTextInput(ic, text);
         if (SPACE_STATE_PHANTOM == mSpaceState) {
             sendKeyCodePoint(Keyboard.CODE_SPACE);
@@ -1433,16 +1431,11 @@
                 ic.deleteSurroundingText(1, 0);
             }
         } else {
-            // We should be very careful about auto-correction cancellation and suggestion
-            // resuming here. The behavior needs to be different according to text field types,
-            // and it would be much clearer to test for them explicitly here rather than
-            // relying on implicit values like "whether the suggestion strip is displayed".
-            if (mLastComposedWord.canCancelAutoCorrect()) {
+            if (mLastComposedWord.canRevertCommit()) {
                 Utils.Stats.onAutoCorrectionCancellation();
-                cancelAutoCorrect(ic);
+                revertCommit(ic);
                 return;
             }
-
             if (SPACE_STATE_DOUBLE == spaceState) {
                 if (revertDoubleSpaceWhileInBatchEdit(ic)) {
                     // No need to reset mSpaceState, it has already be done (that's why we
@@ -1456,61 +1449,27 @@
                 }
             }
 
-            // See the comment above: must be careful about resuming auto-suggestion.
-            if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
-                // Go back to the suggestion mode if the user canceled the
-                // "Touch again to save".
-                // NOTE: In general, we don't revert the word when backspacing
-                // from a manual suggestion pick.  We deliberately chose a
-                // different behavior only in the case of picking the first
-                // suggestion (typed word).  It's intentional to have made this
-                // inconsistent with backspacing after selecting other suggestions.
-                restartSuggestionsOnManuallyPickedTypedWord(ic);
+            // No cancelling of commit/double space/swap: we have a regular backspace.
+            // We should backspace one char and restart suggestion if at the end of a word.
+            if (mLastSelectionStart != mLastSelectionEnd) {
+                // If there is a selection, remove it.
+                final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart;
+                ic.setSelection(mLastSelectionEnd, mLastSelectionEnd);
+                ic.deleteSurroundingText(lengthToDelete, 0);
             } else {
-                // Here we must check whether there is a selection. If so we should remove the
-                // selected text, otherwise we should just delete the character before the cursor.
-                if (mLastSelectionStart != mLastSelectionEnd) {
-                    final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart;
-                    ic.setSelection(mLastSelectionEnd, mLastSelectionEnd);
-                    ic.deleteSurroundingText(lengthToDelete, 0);
-                } else {
-                    if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
-                        // This should never happen.
-                        Log.e(TAG, "Backspace when we don't know the selection position");
-                    }
-                    ic.deleteSurroundingText(1, 0);
-                    if (mDeleteCount > DELETE_ACCELERATE_AT) {
-                        ic.deleteSurroundingText(1, 0);
-                    }
+                // There is no selection, just delete one character.
+                if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
+                    // This should never happen.
+                    Log.e(TAG, "Backspace when we don't know the selection position");
                 }
-                if (isSuggestionsRequested()) {
-                    restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic);
+                ic.deleteSurroundingText(1, 0);
+                if (mDeleteCount > DELETE_ACCELERATE_AT) {
+                    ic.deleteSurroundingText(1, 0);
                 }
             }
-        }
-    }
-
-    // TODO: Implement next and previous actions using other key code than tab's code.
-    private void handleTab() {
-        final int imeOptions = getCurrentInputEditorInfo().imeOptions;
-        if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
-                && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) {
-            // TODO: This should be {@link #sendKeyCodePoint(int)}.
-            sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
-            return;
-        }
-
-        final InputConnection ic = getCurrentInputConnection();
-        if (ic == null)
-            return;
-
-        final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
-        // True if keyboard is in either shift chording or manual shifted state.
-        final boolean isManualShifted = (keyboard != null  && keyboard.isManualShifted());
-        if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) && !isManualShifted) {
-            EditorInfoCompatUtils.performEditorActionNext(ic);
-        } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) && isManualShifted) {
-            EditorInfoCompatUtils.performEditorActionPrevious(ic);
+            if (isSuggestionsRequested()) {
+                restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic);
+            }
         }
     }
 
@@ -1523,10 +1482,10 @@
         } else if ((SPACE_STATE_WEAK == spaceState
                 || SPACE_STATE_SWAP_PUNCTUATION == spaceState)
                 && isFromSuggestionStrip) {
-            if (mSettingsValues.isMagicSpaceSwapper(code)) {
+            if (mSettingsValues.isWeakSpaceSwapper(code)) {
                 return true;
             } else {
-                if (mSettingsValues.isMagicSpaceStripper(code)) {
+                if (mSettingsValues.isWeakSpaceStripper(code)) {
                     removeTrailingSpaceWhileInBatchEdit(ic);
                 }
                 return false;
@@ -1599,6 +1558,15 @@
                 swapSwapperAndSpaceWhileInBatchEdit(ic);
                 mSpaceState = SPACE_STATE_WEAK;
             }
+            // Some characters are not word separators, yet they don't start a new
+            // composing span. For these, we haven't changed the suggestion strip, and
+            // if the "add to dictionary" hint is shown, we should do so now. Examples of
+            // such characters include single quote, dollar, and others; the exact list is
+            // the list of characters for which we enter handleCharacterWhileInBatchEdit
+            // that don't match the test if ((isAlphabet...)) at the top of this method.
+            if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) {
+                mHandler.postUpdateBigramPredictions();
+            }
         }
         Utils.Stats.onNonSeparator((char)primaryCode, x, y);
     }
@@ -1632,7 +1600,7 @@
                 commitCurrentAutoCorrection(primaryCode, ic);
                 didAutoCorrect = true;
             } else {
-                commitTyped(ic);
+                commitTyped(ic, primaryCode);
             }
         }
 
@@ -1689,7 +1657,7 @@
     }
 
     private void handleClose() {
-        commitTyped(getCurrentInputConnection());
+        commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR);
         mVoiceProxy.handleClose();
         requestHideSelf(0);
         LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
@@ -1900,7 +1868,8 @@
             }
             Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
             mExpectingUpdateSelection = true;
-            commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD);
+            commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
+                    separatorCodePoint);
             // Add the word to the user unigram dictionary if it's not a known word
             addToUserUnigramAndBigramDictionaries(autoCorrection,
                     UserUnigramDictionary.FREQUENCY_FOR_TYPED);
@@ -1955,7 +1924,8 @@
         LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
                 suggestion.toString(), index, suggestions.mWords);
         mExpectingUpdateSelection = true;
-        commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK);
+        commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
+                LastComposedWord.NOT_A_SEPARATOR);
         // Add the word to the auto dictionary if it's not a known word
         if (index == 0) {
             addToUserUnigramAndBigramDictionaries(suggestion,
@@ -2005,7 +1975,8 @@
     /**
      * Commits the chosen word to the text field and saves it for later retrieval.
      */
-    private void commitChosenWord(final CharSequence bestWord, final int commitType) {
+    private void commitChosenWord(final CharSequence bestWord, final int commitType,
+            final int separatorCode) {
         final InputConnection ic = getCurrentInputConnection();
         if (ic != null) {
             mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators);
@@ -2019,9 +1990,10 @@
         }
         // TODO: figure out here if this is an auto-correct or if the best word is actually
         // what user typed. Note: currently this is done much later in
-        // LastComposedWord#canCancelAutoCorrect by string equality of the remembered
+        // LastComposedWord#didCommitTypedWord by string equality of the remembered
         // strings.
-        mLastComposedWord = mWordComposer.commitWord(commitType);
+        mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(),
+                separatorCode);
     }
 
     private static final WordComposer sEmptyWordComposer = new WordComposer();
@@ -2183,66 +2155,43 @@
     }
 
     // "ic" must not be null
-    private void cancelAutoCorrect(final InputConnection ic) {
+    private void revertCommit(final InputConnection ic) {
         final String originallyTypedWord = mLastComposedWord.mTypedWord;
-        final CharSequence autoCorrectedTo = mLastComposedWord.mAutoCorrection;
-        final int cancelLength = autoCorrectedTo.length();
-        final CharSequence separator = ic.getTextBeforeCursor(1, 0);
+        final CharSequence committedWord = mLastComposedWord.mCommittedWord;
+        final int cancelLength = committedWord.length();
+        final int separatorLength = mLastComposedWord.getSeparatorLength(
+                mLastComposedWord.mSeparatorCode);
+        // TODO: should we check our saved separator against the actual contents of the text view?
         if (DEBUG) {
             if (mWordComposer.isComposingWord()) {
-                throw new RuntimeException("cancelAutoCorrect, but we are composing a word");
+                throw new RuntimeException("revertCommit, but we are composing a word");
             }
             final String wordBeforeCursor =
-                    ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength)
-                    .toString();
-            if (!TextUtils.equals(autoCorrectedTo, wordBeforeCursor)) {
-                throw new RuntimeException("cancelAutoCorrect check failed: we thought we were "
-                        + "reverting \"" + autoCorrectedTo
+                    ic.getTextBeforeCursor(cancelLength + separatorLength, 0)
+                            .subSequence(0, cancelLength).toString();
+            if (!TextUtils.equals(committedWord, wordBeforeCursor)) {
+                throw new RuntimeException("revertCommit check failed: we thought we were "
+                        + "reverting \"" + committedWord
                         + "\", but before the cursor we found \"" + wordBeforeCursor + "\"");
             }
-            if (TextUtils.equals(originallyTypedWord, wordBeforeCursor)) {
-                throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel "
-                        + "auto correction and revert to \"" + originallyTypedWord
-                        + "\" but we found this very string before the cursor");
-            }
         }
-        ic.deleteSurroundingText(cancelLength + 1, 0);
-        ic.commitText(originallyTypedWord, 1);
-        // Re-insert the separator
-        ic.commitText(separator, 1);
+        ic.deleteSurroundingText(cancelLength + separatorLength, 0);
+        if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) {
+            // This is the case when we cancel a manual pick.
+            // We should restart suggestion on the word right away.
+            mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord);
+            mComposingStateManager.onStartComposingText();
+            ic.setComposingText(originallyTypedWord, 1);
+        } else {
+            ic.commitText(originallyTypedWord, 1);
+            // Re-insert the separator
+            sendKeyCodePoint(mLastComposedWord.mSeparatorCode);
+            Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE,
+                    WordComposer.NOT_A_COORDINATE);
+            // Don't restart suggestion yet. We'll restart if the user deletes the
+            // separator.
+        }
         mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
-        Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE,
-                WordComposer.NOT_A_COORDINATE);
-        mHandler.cancelUpdateBigramPredictions();
-        mHandler.postUpdateSuggestions();
-    }
-
-    // "ic" must not be null
-    private void restartSuggestionsOnManuallyPickedTypedWord(final InputConnection ic) {
-        // Note: this relies on the last word still being held in the WordComposer, in
-        // the field for suggestion resuming.
-        // Note: in the interest of code simplicity, we may want to just call
-        // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving
-        // the old WordComposer allows to reuse the actual typed coordinates.
-        mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord);
-        // We resume suggestion, and then we want to set the composing text to the content
-        // of the word composer again. But since we just manually picked a word, there is
-        // no composing text at the moment, so we have to delete the word before we set a
-        // new composing text.
-        final int restartLength = mWordComposer.size();
-        if (DEBUG) {
-            final String wordBeforeCursor = ic.getTextBeforeCursor(restartLength, 0).toString();
-            if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) {
-                throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord "
-                        + "check failed: we thought we were reverting \""
-                        + mWordComposer.getTypedWord()
-                        + "\", but before the cursor we found \""
-                        + wordBeforeCursor + "\"");
-            }
-        }
-        ic.deleteSurroundingText(restartLength, 0);
-        mComposingStateManager.onStartComposingText();
-        ic.setComposingText(mWordComposer.getTypedWord(), 1);
         mHandler.cancelUpdateBigramPredictions();
         mHandler.postUpdateSuggestions();
     }
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 7a43cb8..d123b60 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -35,8 +35,8 @@
 
     // From resources:
     public final int mDelayUpdateOldSuggestions;
-    public final String mMagicSpaceStrippers;
-    public final String mMagicSpaceSwappers;
+    public final String mWeakSpaceStrippers;
+    public final String mWeakSpaceSwappers;
     private final String mSuggestPuncs;
     public final SuggestedWords mSuggestPuncList;
     public final SuggestedWords mSuggestPuncOutputTextList;
@@ -89,14 +89,14 @@
 
         // Get the resources
         mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
-        mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
-        mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
+        mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols);
+        mWeakSpaceSwappers = res.getString(R.string.weak_space_swapping_symbols);
         if (LatinImeLogger.sDBG) {
-            final int length = mMagicSpaceStrippers.length();
-            for (int i = 0; i < length; i = mMagicSpaceStrippers.offsetByCodePoints(i, 1)) {
-                if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) {
-                    throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i)
-                            + " is both a magic space swapper and stripper.");
+            final int length = mWeakSpaceStrippers.length();
+            for (int i = 0; i < length; i = mWeakSpaceStrippers.offsetByCodePoints(i, 1)) {
+                if (isWeakSpaceSwapper(mWeakSpaceStrippers.codePointAt(i))) {
+                    throw new RuntimeException("Char code " + mWeakSpaceStrippers.codePointAt(i)
+                            + " is both a weak space swapper and stripper.");
                 }
             }
         }
@@ -107,7 +107,7 @@
         mSuggestPuncOutputTextList = createSuggestPuncOutputTextList(suggestPuncsSpec);
         mSymbolsExcludedFromWordSeparators =
                 res.getString(R.string.symbols_excluded_from_word_separators);
-        mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers,
+        mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers,
                 mSymbolsExcludedFromWordSeparators, res);
         mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
 
@@ -188,11 +188,11 @@
         return builder.setIsPunctuationSuggestions().build();
     }
 
-    private static String createWordSeparators(final String magicSpaceStrippers,
-            final String magicSpaceSwappers, final String symbolsExcludedFromWordSeparators,
+    private static String createWordSeparators(final String weakSpaceStrippers,
+            final String weakSpaceSwappers, final String symbolsExcludedFromWordSeparators,
             final Resources res) {
-        String wordSeparators = magicSpaceStrippers + magicSpaceSwappers
-                + res.getString(R.string.magic_space_promoting_symbols);
+        String wordSeparators = weakSpaceStrippers + weakSpaceSwappers
+                + res.getString(R.string.weak_space_promoting_symbols);
         for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
             wordSeparators = wordSeparators.replace(
                     symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
@@ -215,14 +215,14 @@
         return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
     }
 
-    public boolean isMagicSpaceStripper(int code) {
+    public boolean isWeakSpaceStripper(int code) {
         // TODO: this does not work if the code does not fit in a char
-        return mMagicSpaceStrippers.contains(String.valueOf((char)code));
+        return mWeakSpaceStrippers.contains(String.valueOf((char)code));
     }
 
-    public boolean isMagicSpaceSwapper(int code) {
+    public boolean isWeakSpaceSwapper(int code) {
         // TODO: this does not work if the code does not fit in a char
-        return mMagicSpaceSwappers.contains(String.valueOf((char)code));
+        return mWeakSpaceSwappers.contains(String.valueOf((char)code));
     }
 
     private static boolean isAutoCorrectEnabled(final Resources resources,
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 3975ddd..6d63e95 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -264,6 +264,7 @@
             int ret = in % BUFSIZE;
             return ret < 0 ? ret + BUFSIZE : ret;
         }
+        // TODO: accept code points
         public void push(char c, int x, int y) {
             if (!mEnabled) return;
             if (mUsabilityStudy) {
@@ -777,9 +778,10 @@
             LatinImeLogger.logOnInputChar();
         }
 
-        public static void onSeparator(final char code, final int x,
+        public static void onSeparator(final int code, final int x,
                 final int y) {
-            RingCharBuffer.getInstance().push(code, x, y);
+            // TODO: accept code points
+            RingCharBuffer.getInstance().push((char)code, x, y);
             LatinImeLogger.logOnInputSeparator();
         }
 
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index a1a329a..8121ada 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -308,17 +308,11 @@
     }
 
     // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above.
-    public LastComposedWord commitWord(final int type) {
-        // Note: currently, we come here whenever we commit a word. If it's any *other* kind than
-        // DECIDED_WORD, we should reset mAutoCorrection so that we don't attempt to cancel later.
-        // If it's a DECIDED_WORD, it may be an actual auto-correction by the IME, or what the user
-        // typed because the IME decided *not* to auto-correct for whatever reason.
-        // Ideally we would also null it when it was a DECIDED_WORD that was not an auto-correct.
-        // As it happens these two cases should behave differently, because the former can be
-        // canceled while the latter can't. Currently, we figure this out in
-        // LastComposedWord#didAutoCorrectToAnotherWord with #equals(). It would be marginally
-        // cleaner to do it here, but it would be slower (since we would #equals() for each commit,
-        // instead of only on cancel), and ultimately we want to figure it out even earlier anyway.
+    public LastComposedWord commitWord(final int type, final String committedWord,
+            final int separatorCode) {
+        // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
+        // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
+        // the last composed word to ensure this does not happen.
         final ArrayList<int[]> codes = mCodes;
         final int[] xCoordinates = mXCoordinates;
         final int[] yCoordinates = mYCoordinates;
@@ -326,9 +320,9 @@
         mXCoordinates = new int[N];
         mYCoordinates = new int[N];
         final LastComposedWord lastComposedWord = new LastComposedWord(codes,
-                xCoordinates, yCoordinates, mTypedWord.toString(),
-                null == mAutoCorrection ? null : mAutoCorrection.toString());
-        if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD) {
+                xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode);
+        if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
+                && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
             lastComposedWord.deactivate();
         }
         mTypedWord.setLength(0);
@@ -342,6 +336,6 @@
         mYCoordinates = lastComposedWord.mYCoordinates;
         mTypedWord.setLength(0);
         mTypedWord.append(lastComposedWord.mTypedWord);
-        mAutoCorrection = lastComposedWord.mAutoCorrection;
+        mAutoCorrection = null; // This will be filled by the next call to updateSuggestion.
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
index d747a02..e14c71c 100644
--- a/java/src/com/android/inputmethod/latin/XmlParseUtils.java
+++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java
@@ -27,8 +27,7 @@
     @SuppressWarnings("serial")
     public static class ParseException extends XmlPullParserException {
         public ParseException(String msg, XmlPullParser parser) {
-            super(msg + " at line " + parser.getLineNumber()
-                    + ", column " + parser.getColumnNumber());
+            super(msg + " at " + parser.getPositionDescription());
         }
     }
 
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 9d886da3b..78bd4d7 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -169,6 +169,22 @@
                 mTextView.getText().toString());
     }
 
+    public void testPickAutoCorrectionThenBackspace() {
+        final String WORD_TO_TYPE = "tgis";
+        final String WORD_TO_PICK = "this";
+        final String EXPECTED_RESULT = "tgis";
+        type(WORD_TO_TYPE);
+        // Choose the auto-correction, which is always in position 0. For "tgis", the
+        // auto-correction should be "this".
+        mLatinIME.pickSuggestionManually(0, WORD_TO_PICK);
+        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK,
+                mTextView.getText().toString());
+        type(Keyboard.CODE_DELETE);
+        assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT,
+                mTextView.getText().toString());
+    }
+
     public void testPickTypedWordOverAutoCorrectionThenBackspace() {
         final String WORD_TO_TYPE = "tgis";
         final String EXPECTED_RESULT = "tgis";
@@ -177,11 +193,29 @@
         // be occupied by the "this" auto-correction, as checked by testAutoCorrect())
         mLatinIME.pickSuggestionManually(1, WORD_TO_TYPE);
         mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE,
+                mTextView.getText().toString());
         type(Keyboard.CODE_DELETE);
         assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT,
                 mTextView.getText().toString());
     }
 
+    public void testPickDifferentSuggestionThenBackspace() {
+        final String WORD_TO_TYPE = "tgis";
+        final String WORD_TO_PICK = "thus";
+        final String EXPECTED_RESULT = "tgis";
+        type(WORD_TO_TYPE);
+        // Choose the second suggestion, which should be in position 2 and should be "thus"
+        // when "tgis is typed.
+        mLatinIME.pickSuggestionManually(2, WORD_TO_PICK);
+        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        assertEquals("pick different suggestion then backspace", WORD_TO_PICK,
+                mTextView.getText().toString());
+        type(Keyboard.CODE_DELETE);
+        assertEquals("pick different suggestion then backspace", EXPECTED_RESULT,
+                mTextView.getText().toString());
+    }
+
     public void testDeleteSelection() {
         final String STRING_TO_TYPE = "some text delete me some text";
         final int SELECTION_START = 10;
@@ -207,6 +241,23 @@
         assertEquals("simple auto-correct", EXPECTED_RESULT, mTextView.getText().toString());
     }
 
+    public void testAutoCorrectWithPeriod() {
+        final String STRING_TO_TYPE = "tgis.";
+        final String EXPECTED_RESULT = "this.";
+        type(STRING_TO_TYPE);
+        assertEquals("auto-correct with period", EXPECTED_RESULT, mTextView.getText().toString());
+    }
+
+    public void testAutoCorrectWithPeriodThenRevert() {
+        final String STRING_TO_TYPE = "tgis.";
+        final String EXPECTED_RESULT = "tgis.";
+        type(STRING_TO_TYPE);
+        mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+        type(Keyboard.CODE_DELETE);
+        assertEquals("auto-correct with period then revert", EXPECTED_RESULT,
+                mTextView.getText().toString());
+    }
+
     public void testDoubleSpace() {
         final String STRING_TO_TYPE = "this  ";
         final String EXPECTED_RESULT = "this. ";