Merge "Fix some of the input logic tests" into jb-dev
diff --git a/dictionaries/de_wordlist.xml b/dictionaries/de_wordlist.xml
index 40140f5..c7e46c6 100644
--- a/dictionaries/de_wordlist.xml
+++ b/dictionaries/de_wordlist.xml
@@ -1,9 +1,10 @@
-<wordlist locale="de" description="Allgemeines Wörterbuch" date="1337171108" version="7" options="german_umlaut_processing">
+<wordlist locale="de" description="Deutsch" date="1337654924" version="10" options="german_umlaut_processing">
  <w f="203" flags="">der</w>
  <w f="200" flags="">und</w>
  <w f="198" flags="">die</w>
  <w f="195" flags="">in</w>
  <w f="191" flags="">von</w>
+ <w f="190">über</w>
  <w f="188" flags="">den</w>
  <w f="186" flags="">des</w>
  <w f="185" flags="">im</w>
diff --git a/dictionaries/en_GB_wordlist.xml b/dictionaries/en_GB_wordlist.xml
index b2d703c..79ce932 100644
--- a/dictionaries/en_GB_wordlist.xml
+++ b/dictionaries/en_GB_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en_GB" description="Main dictionary (UK English)" date="1337328254" version="8">
+<wordlist locale="en_GB" description="English (UK)" date="1337670570" version="10">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -45,6 +45,7 @@
  <w f="174" flags="">time</w>
  <w f="173" flags="">all</w>
  <w f="173" flags="">be</w>
+ <w f="173" flags="">me</w>
  <w f="173" flags="">more</w>
  <w f="172" flags="">only</w>
  <w f="172" flags="">when</w>
@@ -164,6 +165,7 @@
  <w f="160" flags="">us</w>
  <w f="160" flags="">very</w>
  <w f="160" flags="">won</w>
+ <w f="160" flags="">yes</w>
  <w f="160" flags="">you're</w>
  <w f="159" flags="">along</w>
  <w f="159" flags="">built</w>
@@ -1157,7 +1159,7 @@
  <w f="138" flags="">little</w>
  <w f="138" flags="">mass</w>
  <w f="138" flags="">matches</w>
- <w f="138" flags="">me</w>
+ <w f="138" flags="">meat</w>
  <w f="138" flags="">offer</w>
  <w f="138" flags="">parties</w>
  <w f="138" flags="">pay</w>
@@ -3128,6 +3130,7 @@
  <w f="125" flags="">temperatures</w>
  <w f="125" flags="">tenure</w>
  <w f="125" flags="">thinking</w>
+ <w f="125">this'd</w>
  <w f="125" flags="">tone</w>
  <w f="125" flags="">tourist</w>
  <w f="125" flags="">trail</w>
@@ -3264,7 +3267,6 @@
  <w f="124" flags="">maps</w>
  <w f="124" flags="">marks</w>
  <w f="124" flags="">measured</w>
- <w f="124" flags="">meat</w>
  <w f="124" flags="">memorial</w>
  <w f="124" flags="">met</w>
  <w f="124" flags="">mines</w>
@@ -4150,6 +4152,7 @@
  <w f="120" flags="">fun</w>
  <w f="120" flags="">gallery</w>
  <w f="120" flags="">girlfriend</w>
+ <w f="120">gmail</w>
  <w f="120" flags="">grain</w>
  <w f="120" flags="">grass</w>
  <w f="120" flags="">guidance</w>
@@ -4285,6 +4288,7 @@
  <w f="120" flags="">thrown</w>
  <w f="120" flags="">tomorrow</w>
  <w f="120" flags="">tonight</w>
+ <w f="120">totally</w>
  <w f="120" flags="">towers</w>
  <w f="120" flags="">transformation</w>
  <w f="120" flags="">transported</w>
@@ -5072,7 +5076,6 @@
  <w f="117" flags="">tobacco</w>
  <w f="117" flags="">topped</w>
  <w f="117" flags="">torpedo</w>
- <w f="117" flags="">totally</w>
  <w f="117" flags="">trace</w>
  <w f="117" flags="">transform</w>
  <w f="117" flags="">transmitted</w>
@@ -5552,6 +5555,7 @@
  <w f="115" flags="">heated</w>
  <w f="115" flags="">honours</w>
  <w f="115" flags="">hoping</w>
+ <w f="115">how're</w>
  <w f="115" flags="">hunt</w>
  <w f="115" flags="">immigrant</w>
  <w f="115" flags="">inaugurated</w>
@@ -8019,6 +8023,7 @@
  <w f="108" flags="">dug</w>
  <w f="108" flags="">dwarf</w>
  <w f="108" flags="">dwellings</w>
+ <w f="108">e-mail</w>
  <w f="108" flags="">economist</w>
  <w f="108" flags="">elevator</w>
  <w f="108" flags="">embraced</w>
@@ -11130,7 +11135,6 @@
  <w f="102" flags="">worms</w>
  <w f="102" flags="">wrestled</w>
  <w f="102" flags="">yeast</w>
- <w f="102" flags="">yes</w>
  <w f="101" flags="">Abdul</w>
  <w f="101" flags="">Aberdeen</w>
  <w f="101" flags="">Adolf</w>
@@ -11735,6 +11739,7 @@
  <w f="100" flags="">balancing</w>
  <w f="100" flags="">balloons</w>
  <w f="100" flags="">banquet</w>
+ <w f="100">barbeque</w>
  <w f="100" flags="">barge</w>
  <w f="100" flags="">barley</w>
  <w f="100" flags="">basilica</w>
@@ -12898,6 +12903,7 @@
  <w f="98" flags="">Rex</w>
  <w f="98" flags="">Riley</w>
  <w f="98" flags="abreviation">SBS</w>
+ <w f="98">SMS</w>
  <w f="98" flags="">Salisbury</w>
  <w f="98" flags="">Santos</w>
  <w f="98" flags="">Saturn</w>
@@ -13135,6 +13141,7 @@
  <w f="98" flags="">flu</w>
  <w f="98" flags="">fluorescent</w>
  <w f="98" flags="">flush</w>
+ <w f="98">foe</w>
  <w f="98" flags="">footprint</w>
  <w f="98" flags="">forecasts</w>
  <w f="98" flags="">foreground</w>
@@ -13408,6 +13415,7 @@
  <w f="98" flags="">thrash</w>
  <w f="98" flags="">thyroid</w>
  <w f="98" flags="">tides</w>
+ <w f="98">timeframe</w>
  <w f="98" flags="">tolerated</w>
  <w f="98" flags="">tolls</w>
  <w f="98" flags="">tonal</w>
@@ -15178,6 +15186,7 @@
  <w f="95" flags="">nephews</w>
  <w f="95" flags="">netted</w>
  <w f="95" flags="">numeric</w>
+ <w f="95">nut</w>
  <w f="95" flags="">obey</w>
  <w f="95" flags="">obscured</w>
  <w f="95" flags="">obverse</w>
@@ -21006,6 +21015,7 @@
  <w f="88" flags="">wafer</w>
  <w f="88" flags="">warmed</w>
  <w f="88" flags="">wasps</w>
+ <w f="88">wax</w>
  <w f="88" flags="">wellness</w>
  <w f="88" flags="">whistles</w>
  <w f="88" flags="">wills</w>
@@ -26639,7 +26649,6 @@
  <w f="82" flags="">gust</w>
  <w f="82" flags="">guts</w>
  <w f="82" flags="">gymnasiums</w>
- <w f="82">ha-ha</w>
  <w f="82">half-life</w>
  <w f="82" flags="">halides</w>
  <w f="82" flags="">hallucinogenic</w>
@@ -27187,6 +27196,7 @@
  <w f="81" flags="">Ares</w>
  <w f="81" flags="">Argonauts</w>
  <w f="81" flags="">Ashkenazi</w>
+ <w f="81">Asus</w>
  <w f="81" flags="">Athenians</w>
  <w f="81" flags="">Augustinian</w>
  <w f="81" flags="">Austen</w>
@@ -28590,6 +28600,7 @@
  <w f="80" flags="">Weinberg</w>
  <w f="80" flags="">Westmoreland</w>
  <w f="80" flags="">Westport</w>
+ <w f="80">Wi-Fi</w>
  <w f="80" flags="">Wilfrid</w>
  <w f="80" flags="">Windham</w>
  <w f="80" flags="">Worthington</w>
@@ -28893,6 +28904,7 @@
  <w f="80" flags="">evangelistic</w>
  <w f="80" flags="">evaporate</w>
  <w f="80" flags="">eventing</w>
+ <w f="80">everything's</w>
  <w f="80" flags="">excision</w>
  <w f="80" flags="">exclaims</w>
  <w f="80" flags="">exerting</w>
@@ -29565,6 +29577,7 @@
  <w f="79" flags="">Guatemalan</w>
  <w f="79" flags="">Guevara</w>
  <w f="79" flags="">Gustavo</w>
+ <w f="79">HTC</w>
  <w f="79" flags="abreviation">HVDC</w>
  <w f="79" flags="">Haines</w>
  <w f="79" flags="">Hannover</w>
@@ -30119,6 +30132,7 @@
  <w f="79" flags="">genre's</w>
  <w f="79" flags="">geometrically</w>
  <w f="79" flags="">ghee</w>
+ <w f="79">girls'</w>
  <w f="79" flags="">glandular</w>
  <w f="79" flags="">glittering</w>
  <w f="79" flags="">goaltending</w>
@@ -30261,6 +30275,7 @@
  <w f="79" flags="">metamorphosed</w>
  <w f="79" flags="">midterm</w>
  <w f="79" flags="">midtown</w>
+ <w f="79">might've</w>
  <w f="79" flags="">millionaires</w>
  <w f="79" flags="">mindful</w>
  <w f="79" flags="">ministered</w>
@@ -30386,6 +30401,7 @@
  <w f="79" flags="">quilt</w>
  <w f="79" flags="">race's</w>
  <w f="79" flags="">radio's</w>
+ <w f="79">ramen</w>
  <w f="79" flags="">rapprochement</w>
  <w f="79" flags="">rayon</w>
  <w f="79" flags="">readability</w>
@@ -32278,6 +32294,7 @@
  <w f="77" flags="abreviation">WG</w>
  <w f="77" flags="abreviation">WNEW</w>
  <w f="77" flags="">Walloon</w>
+ <w f="77">Walmart</w>
  <w f="77" flags="">Weldon</w>
  <w f="77" flags="">Weller</w>
  <w f="77" flags="">Whitlam</w>
@@ -32528,6 +32545,7 @@
  <w f="77" flags="">echolocation</w>
  <w f="77" flags="">ecologist</w>
  <w f="77" flags="">ecologists</w>
+ <w f="77">editors'</w>
  <w f="77" flags="">effigies</w>
  <w f="77" flags="">egos</w>
  <w f="77" flags="">electrocution</w>
@@ -33010,6 +33028,7 @@
  <w f="77" flags="">slimmer</w>
  <w f="77" flags="">slipper</w>
  <w f="77" flags="">slurs</w>
+ <w f="77">smartphone</w>
  <w f="77" flags="">smokes</w>
  <w f="77" flags="">snapshots</w>
  <w f="77" flags="">snorkeling</w>
@@ -33042,6 +33061,7 @@
  <w f="77" flags="">squall</w>
  <w f="77" flags="">squandered</w>
  <w f="77" flags="">stares</w>
+ <w f="77">states'</w>
  <w f="77" flags="">steelhead</w>
  <w f="77" flags="">stencil</w>
  <w f="77" flags="">stepbrother</w>
@@ -33166,6 +33186,7 @@
  <w f="77" flags="">wedged</w>
  <w f="77" flags="">weeklies</w>
  <w f="77" flags="">wellbeing</w>
+ <w f="77">whatever's</w>
  <w f="77" flags="">whistleblower</w>
  <w f="77" flags="">wickedness</w>
  <w f="77" flags="">wilt</w>
@@ -34205,6 +34226,7 @@
  <w f="76" flags="">rationalisation</w>
  <w f="76" flags="">ravaging</w>
  <w f="76" flags="">reacquired</w>
+ <w f="76">readers'</w>
  <w f="76" flags="">realtime</w>
  <w f="76" flags="">reanimated</w>
  <w f="76" flags="">reapportionment</w>
@@ -34263,6 +34285,7 @@
  <w f="76" flags="">scents</w>
  <w f="76" flags="">schoolboys</w>
  <w f="76" flags="">schoolmates</w>
+ <w f="76">sci-fi</w>
  <w f="76" flags="">scooped</w>
  <w f="76" flags="">scoops</w>
  <w f="76" flags="">scopes</w>
@@ -34447,6 +34470,7 @@
  <w f="76" flags="">waxing</w>
  <w f="76" flags="">whaler</w>
  <w f="76" flags="">wheelers</w>
+ <w f="76">whenever's</w>
  <w f="76" flags="">whey</w>
  <w f="76" flags="">whitewashed</w>
  <w f="76" flags="">wholeheartedly</w>
@@ -35390,6 +35414,7 @@
  <w f="75" flags="">nomad</w>
  <w f="75" flags="">nonempty</w>
  <w f="75" flags="">nonverbal</w>
+ <w f="75">now's</w>
  <w f="75" flags="">obscures</w>
  <w f="75" flags="">obsessions</w>
  <w f="75" flags="">occultism</w>
@@ -35751,7 +35776,9 @@
  <w f="75" flags="">wedded</w>
  <w f="75" flags="">weft</w>
  <w f="75" flags="">westerners</w>
+ <w f="75">what'll</w>
  <w f="75" flags="">whistled</w>
+ <w f="75">whoever's</w>
  <w f="75" flags="">winegrowing</w>
  <w f="75" flags="">wintered</w>
  <w f="75" flags="">withstanding</w>
@@ -35809,6 +35836,7 @@
  <w f="74" flags="">Ben's</w>
  <w f="74" flags="">Benetton</w>
  <w f="74" flags="">Bevan</w>
+ <w f="74">Beyonce</w>
  <w f="74" flags="">Billy's</w>
  <w f="74" flags="">Biscayne</w>
  <w f="74" flags="">Blackadder</w>
@@ -36395,6 +36423,7 @@
  <w f="74" flags="">ellipsis</w>
  <w f="74" flags="">emanate</w>
  <w f="74" flags="">embalming</w>
+ <w f="74">emo</w>
  <w f="74" flags="">empathic</w>
  <w f="74" flags="">encroachments</w>
  <w f="74" flags="">engravers</w>
@@ -36528,6 +36557,7 @@
  <w f="74" flags="">hoppers</w>
  <w f="74" flags="">horoscope</w>
  <w f="74" flags="">housings</w>
+ <w f="74">how'd</w>
  <w f="74" flags="">humus</w>
  <w f="74" flags="">hussars</w>
  <w f="74" flags="">hustle</w>
@@ -56886,6 +56916,7 @@
  <w f="60" flags="">megacity</w>
  <w f="60" flags="">megalith</w>
  <w f="60" flags="">megalomania</w>
+ <w f="60">meme</w>
  <w f="60" flags="">memorial's</w>
  <w f="60" flags="">memorised</w>
  <w f="60" flags="">metafiction</w>
@@ -108059,6 +108090,7 @@
  <w f="25" flags="">Chernobyl's</w>
  <w f="25" flags="">Chesapeake's</w>
  <w f="25" flags="">Cheviots</w>
+ <w f="25">Chewbacca</w>
  <w f="25" flags="">Chimer</w>
  <w f="25" flags="">Chippendale's</w>
  <w f="25" flags="">Chretien's</w>
@@ -138949,6 +138981,7 @@
  <w f="1" flags="">Irrelative</w>
  <w f="1" flags="">Irtysh's</w>
  <w f="1" flags="">Irv's</w>
+ <w f="1">Isaac</w>
  <w f="1" flags="">Isadore's</w>
  <w f="1" flags="">Isidro's</w>
  <w f="1" flags="">Islamism's</w>
@@ -142637,6 +142670,7 @@
  <w f="1" flags="">Thunderclap's</w>
  <w f="1" flags="">Thunderer's</w>
  <w f="1" flags="">Thunderhead's</w>
+ <w f="1">Thur</w>
  <w f="1" flags="">Thurgau's</w>
  <w f="1" flags="">Thwacker</w>
  <w f="1" flags="">Thwarter</w>
@@ -143391,6 +143425,7 @@
  <w f="1" flags="">Xhosa's</w>
  <w f="1" flags="">Ximenes's</w>
  <w f="1" flags="">Ximenez's</w>
+ <w f="1">Xoom</w>
  <w f="1" flags="abreviation">YMMV</w>
  <w f="1" flags="">Yachtsman's</w>
  <w f="1" flags="">Yachtswoman's</w>
@@ -148396,6 +148431,7 @@
  <w f="1" flags="">hypothesiser</w>
  <w f="1" flags="">hypothesists</w>
  <w f="1" flags="">hysteroid</w>
+ <w f="1">iOS</w>
  <w f="1" flags="">ibuprofens</w>
  <w f="1" flags="">ichthyoid</w>
  <w f="1" flags="">iconography's</w>
@@ -152501,6 +152537,7 @@
  <w f="1" flags="">runers</w>
  <w f="1" flags="">runlet</w>
  <w f="1" flags="">runoff's</w>
+ <w f="1">runtime</w>
  <w f="1" flags="">rupture's</w>
  <w f="1" flags="">ruralists</w>
  <w f="1" flags="">ruralites</w>
@@ -155820,6 +155857,7 @@
  <w f="0" flags="medical">clitorises</w>
  <w f="0" flags="medical">cloaca</w>
  <w f="0" flags="medical">clyster</w>
+ <w f="0">cmon</w>
  <w f="0" flags="abreviation">co</w>
  <w f="0" flags="">cock</w>
  <w f="0" flags="">cockier</w>
@@ -155907,6 +155945,7 @@
  <w f="0" flags="offensive">dildo</w>
  <w f="0" flags="offensive">dildos</w>
  <w f="0" flags="n">dirty</w>
+ <w f="0">dogfood</w>
  <w f="0" flags="n">dogging</w>
  <w f="0" flags="medical">dominatrices</w>
  <w f="0" flags="n">dong</w>
@@ -155978,6 +156017,7 @@
  <w f="0" flags="offensive">farted</w>
  <w f="0" flags="offensive">farting</w>
  <w f="0" flags="offensive">farts</w>
+ <w f="0">fave</w>
  <w f="0" flags="medical">fecaliths</w>
  <w f="0" flags="medical">fellate</w>
  <w f="0" flags="medical">fellated</w>
@@ -156030,6 +156070,7 @@
  <w f="0" flags="n">gangbangs</w>
  <w f="0" flags="n">gaping</w>
  <w f="0" flags="">geek</w>
+ <w f="0">geez</w>
  <w f="0" flags="medical">genital</w>
  <w f="0" flags="medical">genitalia</w>
  <w f="0" flags="medical">genitalic</w>
@@ -156372,6 +156413,7 @@
  <w f="0" flags="">playgirl</w>
  <w f="0" flags="">playgirls</w>
  <w f="0" flags="n">playmates</w>
+ <w f="0">pls</w>
  <w f="0" flags="n">plumper</w>
  <w f="0" flags="">poi</w>
  <w f="0" flags="">pol</w>
@@ -156678,6 +156720,7 @@
  <w f="0" flags="medical">testicles</w>
  <w f="0" flags="medical">testicular</w>
  <w f="0" flags="medical">testis</w>
+ <w f="0">thingy</w>
  <w f="0" flags="">threesome</w>
  <w f="0" flags="">threesomes</w>
  <w f="0" flags="">thud</w>
@@ -156718,6 +156761,7 @@
  <w f="0" flags="babytalk">twat</w>
  <w f="0" flags="babytalk">twats</w>
  <w f="0" flags="">twit</w>
+ <w f="0">ull</w>
  <w f="0" flags="babytalk">underclothing</w>
  <w f="0" flags="babytalk">underwear</w>
  <w f="0" flags="babytalk">undy</w>
diff --git a/dictionaries/en_US_wordlist.xml b/dictionaries/en_US_wordlist.xml
index 1e14da4..075a104 100644
--- a/dictionaries/en_US_wordlist.xml
+++ b/dictionaries/en_US_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en_GB" description="Main dictionary (US English)" date="1337328218" version="8">
+<wordlist locale="en_US" description="English (US)" date="1337667777" version="10">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -45,6 +45,7 @@
  <w f="174" flags="">time</w>
  <w f="173" flags="">all</w>
  <w f="173" flags="">be</w>
+ <w f="173" flags="">me</w>
  <w f="173" flags="">more</w>
  <w f="172" flags="">only</w>
  <w f="172" flags="">when</w>
@@ -163,6 +164,7 @@
  <w f="160" flags="">us</w>
  <w f="160" flags="">very</w>
  <w f="160" flags="">won</w>
+ <w f="160" flags="">yes</w>
  <w f="160" flags="">you're</w>
  <w f="159" flags="">along</w>
  <w f="159" flags="">built</w>
@@ -1168,7 +1170,7 @@
  <w f="138" flags="">little</w>
  <w f="138" flags="">mass</w>
  <w f="138" flags="">matches</w>
- <w f="138" flags="">me</w>
+ <w f="138" flags="">meat</w>
  <w f="138" flags="">offer</w>
  <w f="138" flags="">parties</w>
  <w f="138" flags="">pay</w>
@@ -3337,7 +3339,6 @@
  <w f="124" flags="">maps</w>
  <w f="124" flags="">marks</w>
  <w f="124" flags="">measured</w>
- <w f="124" flags="">meat</w>
  <w f="124" flags="">memorial</w>
  <w f="124" flags="">met</w>
  <w f="124" flags="">mines</w>
@@ -11481,7 +11482,6 @@
  <w f="102" flags="">worms</w>
  <w f="102" flags="">wrestled</w>
  <w f="102" flags="">yeast</w>
- <w f="102" flags="">yes</w>
  <w f="101" flags="">Abdul</w>
  <w f="101" flags="">Aberdeen</w>
  <w f="101" flags="">Adolf</w>
@@ -27696,7 +27696,6 @@
  <w f="82" flags="">gust</w>
  <w f="82" flags="">guts</w>
  <w f="82" flags="">gymnasiums</w>
- <w f="82">ha-ha</w>
  <w f="82">half-life</w>
  <w f="82" flags="">halides</w>
  <w f="82" flags="">hallucinogenic</w>
@@ -59001,6 +59000,7 @@
  <w f="60" flags="">megacity</w>
  <w f="60" flags="">megalith</w>
  <w f="60" flags="">megalomania</w>
+ <w f="60">meme</w>
  <w f="60" flags="">memorial's</w>
  <w f="60" flags="">metafiction</w>
  <w f="60" flags="">metamorphoses</w>
diff --git a/dictionaries/en_wordlist.xml b/dictionaries/en_wordlist.xml
index 3839fb8..eff5fd2 100644
--- a/dictionaries/en_wordlist.xml
+++ b/dictionaries/en_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="en" description="Main dictionary" date="1337248980" version="7">
+<wordlist locale="en" description="English" date="1337667811" version="10">
  <w f="222" flags="">the</w>
  <w f="214" flags="">of</w>
  <w f="212" flags="">and</w>
@@ -45,6 +45,7 @@
  <w f="174" flags="">time</w>
  <w f="173" flags="">all</w>
  <w f="173" flags="">be</w>
+ <w f="173" flags="">me</w>
  <w f="173" flags="">more</w>
  <w f="172" flags="">only</w>
  <w f="172" flags="">when</w>
@@ -163,6 +164,7 @@
  <w f="160" flags="">us</w>
  <w f="160" flags="">very</w>
  <w f="160" flags="">won</w>
+ <w f="160" flags="">yes</w>
  <w f="160" flags="">you're</w>
  <w f="159" flags="">along</w>
  <w f="159" flags="">built</w>
@@ -803,7 +805,6 @@
  <w f="143" flags="">variety</w>
  <w f="143" flags="">view</w>
  <w f="142" flags="">German</w>
- <w f="142" flags="">I</w>
  <w f="142" flags="">London</w>
  <w f="142" flags="">West</w>
  <w f="142" flags="">actually</w>
@@ -1171,7 +1172,7 @@
  <w f="138" flags="">little</w>
  <w f="138" flags="">mass</w>
  <w f="138" flags="">matches</w>
- <w f="138" flags="">me</w>
+ <w f="138" flags="">meat</w>
  <w f="138" flags="">offer</w>
  <w f="138" flags="">parties</w>
  <w f="138" flags="">pay</w>
@@ -3351,7 +3352,6 @@
  <w f="124" flags="">maps</w>
  <w f="124" flags="">marks</w>
  <w f="124" flags="">measured</w>
- <w f="124" flags="">meat</w>
  <w f="124" flags="">memorial</w>
  <w f="124" flags="">met</w>
  <w f="124" flags="">mines</w>
@@ -11571,7 +11571,6 @@
  <w f="102" flags="">worms</w>
  <w f="102" flags="">wrestled</w>
  <w f="102" flags="">yeast</w>
- <w f="102" flags="">yes</w>
  <w f="101" flags="">Abdul</w>
  <w f="101" flags="">Aberdeen</w>
  <w f="101" flags="">Adolf</w>
@@ -11625,7 +11624,6 @@
  <w f="101" flags="">Lynn</w>
  <w f="101" flags="">Lyon</w>
  <w f="101" flags="abreviation">MCC</w>
- <w f="101" flags="">Mac</w>
  <w f="101" flags="">Macedonia</w>
  <w f="101" flags="">Malay</w>
  <w f="101" flags="">Martha</w>
@@ -13698,7 +13696,6 @@
  <w f="98" flags="">flu</w>
  <w f="98" flags="">fluorescent</w>
  <w f="98" flags="">flush</w>
- <w f="98">foe</w>
  <w f="98" flags="">footprint</w>
  <w f="98" flags="">forecasts</w>
  <w f="98" flags="">foreground</w>
@@ -15875,7 +15872,6 @@
  <w f="95" flags="">nephews</w>
  <w f="95" flags="">netted</w>
  <w f="95" flags="">numeric</w>
- <w f="95">nut</w>
  <w f="95" flags="">obey</w>
  <w f="95" flags="">obscured</w>
  <w f="95" flags="">obverse</w>
@@ -22053,7 +22049,6 @@
  <w f="88" flags="">wafer</w>
  <w f="88" flags="">warmed</w>
  <w f="88" flags="">wasps</w>
- <w f="88">wax</w>
  <w f="88" flags="">wellness</w>
  <w f="88" flags="">whistles</w>
  <w f="88" flags="">wills</w>
@@ -28032,7 +28027,6 @@
  <w f="82" flags="">gust</w>
  <w f="82" flags="">guts</w>
  <w f="82" flags="">gymnasiums</w>
- <w f="82">ha-ha</w>
  <w f="82">half-life</w>
  <w f="82" flags="">halides</w>
  <w f="82" flags="">hallucinogenic</w>
@@ -41924,7 +41918,6 @@
  <w f="71" flags="abreviation">CFCs</w>
  <w f="71" flags="abreviation">CLS</w>
  <w f="71" flags="abreviation">CMF</w>
- <w f="71" flags="abreviation">CNA</w>
  <w f="71" flags="abreviation">CTP</w>
  <w f="71" flags="">Cabral</w>
  <w f="71" flags="">Caligula</w>
@@ -59972,6 +59965,7 @@
  <w f="60" flags="">megacity</w>
  <w f="60" flags="">megalith</w>
  <w f="60" flags="">megalomania</w>
+ <w f="60">meme</w>
  <w f="60" flags="">memorial's</w>
  <w f="60" flags="">memorised</w>
  <w f="60" flags="">metafiction</w>
@@ -60718,7 +60712,6 @@
  <w f="59" flags="abreviation">IEE</w>
  <w f="59" flags="abreviation">IPSC</w>
  <w f="59" flags="abreviation">IRBM</w>
- <w f="59" flags="abreviation">ITIS</w>
  <w f="59" flags="">Ilkeston</w>
  <w f="59" flags="">InfoWorld</w>
  <w f="59" flags="">Infosys</w>
@@ -69231,7 +69224,6 @@
  <w f="54" flags="">Honshu</w>
  <w f="54" flags="">Hui's</w>
  <w f="54" flags="abreviation">IBSF</w>
- <w f="54" flags="abreviation">ITD</w>
  <w f="54" flags="">Ibrahim's</w>
  <w f="54" flags="">Imogene</w>
  <w f="54" flags="">Inmarsat</w>
@@ -114336,6 +114328,7 @@
  <w f="25" flags="">Chernobyl's</w>
  <w f="25" flags="">Chesapeake's</w>
  <w f="25" flags="">Cheviots</w>
+ <w f="25">Chewbacca</w>
  <w f="25" flags="">Chimer</w>
  <w f="25" flags="">Chippendale's</w>
  <w f="25" flags="">Chretien's</w>
@@ -146792,7 +146785,6 @@
  <w f="1" flags="">Irrelative</w>
  <w f="1" flags="">Irtysh's</w>
  <w f="1" flags="">Irv's</w>
- <w f="1">Isaac</w>
  <w f="1" flags="">Isadore's</w>
  <w f="1" flags="">Isidro's</w>
  <w f="1" flags="">Islamism's</w>
@@ -160937,7 +160929,6 @@
  <w f="1" flags="">runers</w>
  <w f="1" flags="">runlet</w>
  <w f="1" flags="">runoff's</w>
- <w f="1">runtime</w>
  <w f="1" flags="">rupture's</w>
  <w f="1" flags="">ruralists</w>
  <w f="1" flags="">ruralites</w>
diff --git a/dictionaries/es_wordlist.xml b/dictionaries/es_wordlist.xml
index d7f0ac3..cfaa7d9 100644
--- a/dictionaries/es_wordlist.xml
+++ b/dictionaries/es_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="es" description="Diccionario principal" date="1337171277" version="7">
+<wordlist locale="es" description="Español" date="1337655036" version="10">
  <w f="207" flags="">de</w>
  <w f="198" flags="">la</w>
  <w f="196" flags="">en</w>
diff --git a/dictionaries/fa_wordlist.xml b/dictionaries/fa_wordlist.xml
index a0e417a..ba7c4c0 100644
--- a/dictionaries/fa_wordlist.xml
+++ b/dictionaries/fa_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="fa" description="فرهنگ‌ لغت اصلی" date="1337171515" version="7">
+<wordlist locale="fa" description="\u067E\u0627\u0631\u0633\u06CC\u000A" date="1337655087" version="10">
  <w f="168" flags="">و</w>
  <w f="167" flags="">در</w>
  <w f="163" flags="">به</w>
diff --git a/dictionaries/fr_wordlist.xml b/dictionaries/fr_wordlist.xml
index cb047a4..1e0436c 100644
--- a/dictionaries/fr_wordlist.xml
+++ b/dictionaries/fr_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="fr" description="Dictionnaire principal" date="1337330537" version="8" options="french_ligature_processing">
+<wordlist locale="fr" description="Français" date="1337655131" version="10" options="french_ligature_processing">
  <w f="209" flags="">de</w>
  <w f="200" flags="">la</w>
  <w f="197" flags="">et</w>
diff --git a/dictionaries/hr_wordlist.xml b/dictionaries/hr_wordlist.xml
index fe79d59..639feef 100644
--- a/dictionaries/hr_wordlist.xml
+++ b/dictionaries/hr_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="hr" description="Glavni rječnik" date="1337171563" version="7">
+<wordlist locale="hr" description="Hrvatski" date="1337655174" version="10">
  <w f="165" flags="">je</w>
  <w f="164" flags="">i</w>
  <w f="162" flags="">u</w>
diff --git a/dictionaries/it_wordlist.xml b/dictionaries/it_wordlist.xml
index dfb9fca..33f475e 100644
--- a/dictionaries/it_wordlist.xml
+++ b/dictionaries/it_wordlist.xml
@@ -1,4 +1,4 @@
-<wordlist locale="it" description="Dizionario principale" date="1337171609" version="7">
+<wordlist locale="it" description="Italiano" date="1337655212" version="10">
  <w f="199" flags="">di</w>
  <w f="193" flags="">e</w>
  <w f="189" flags="">il</w>
diff --git a/dictionaries/pt_wordlist.xml b/dictionaries/pt_BR_wordlist.xml
similarity index 99%
rename from dictionaries/pt_wordlist.xml
rename to dictionaries/pt_BR_wordlist.xml
index 4129797..cae7f12 100644
--- a/dictionaries/pt_wordlist.xml
+++ b/dictionaries/pt_BR_wordlist.xml
@@ -1,4 +1,4 @@
-nil
+<wordlist locale="pt_BR" description="Portugês (Brasil)" date="1337655248" version="10">
  <w f="193" flags="">de</w>
  <w f="183" flags="">a</w>
  <w f="183" flags="">e</w>
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 393bc18..06d852b 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -30,7 +30,8 @@
             <meta-data android:name="android.view.textservice.scs" android:resource="@xml/spellchecker" />
         </service>
 
-        <activity android:name="SettingsActivity" android:label="@string/english_ime_settings">
+        <activity android:name="SettingsActivity" android:label="@string/english_ime_settings"
+                  android:uiOptions="splitActionBarWhenNarrow">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict
index 68b0dce..1a7b305 100644
--- a/java/res/raw/main_de.dict
+++ b/java/res/raw/main_de.dict
Binary files differ
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index f544da6..14865a2 100644
--- a/java/res/raw/main_en.dict
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 8321c70..71370aa 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 084ef7c..4723961 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/raw/main_it.dict b/java/res/raw/main_it.dict
index ed260f2..00bbdbe 100644
--- a/java/res/raw/main_it.dict
+++ b/java/res/raw/main_it.dict
Binary files differ
diff --git a/java/res/values-en/whitelist.xml b/java/res/values-en/whitelist.xml
index bcb884e..0a1646f 100644
--- a/java/res/values-en/whitelist.xml
+++ b/java/res/values-en/whitelist.xml
@@ -30,62 +30,15 @@
         <item>ill</item>
         <item>I\'ll</item>
 
-        <!-- Following entries came from AutoText -->
-        <!-- TODO: Trim down these entries by removing ones getting auto-corrected by the typing
-                error correction algorithms. -->
-        <item>255</item>
-        <item>abouta</item>
-        <item>about a</item>
-
-        <item>255</item>
-        <item>aboutit</item>
-        <item>about it</item>
-
-        <item>255</item>
-        <item>aboutthe</item>
-        <item>about the</item>
-
-        <item>255</item>
-        <item>acheive</item>
-        <item>achieve</item>
-
-        <item>255</item>
-        <item>acheived</item>
-        <item>achieved</item>
-
-        <item>255</item>
-        <item>acheiving</item>
-        <item>achieving</item>
+        <!-- Following entries came from AutoText the Android keyboard no longer uses. -->
+        <!-- TODO: Trim down more entries by removing ones that get auto-corrected by the
+             Android keyboard's own typing error correction algorithms. -->
 
         <item>255</item>
         <item>acomodate</item>
         <item>accommodate</item>
 
         <item>255</item>
-        <item>accomodate</item>
-        <item>accommodate</item>
-
-        <item>255</item>
-        <item>acn</item>
-        <item>can</item>
-
-        <item>255</item>
-        <item>adn</item>
-        <item>and</item>
-
-        <item>255</item>
-        <item>agian</item>
-        <item>again</item>
-
-        <item>255</item>
-        <item>ahd</item>
-        <item>had</item>
-
-        <item>255</item>
-        <item>ahve</item>
-        <item>have</item>
-
-        <item>255</item>
         <item>aint</item>
         <item>ain\'t</item>
 
@@ -94,82 +47,14 @@
         <item>a lot</item>
 
         <item>255</item>
-        <item>amde</item>
-        <item>made</item>
-
-        <item>255</item>
-        <item>amke</item>
-        <item>make</item>
-
-        <item>255</item>
-        <item>andone</item>
-        <item>and one</item>
-
-        <item>255</item>
         <item>andteh</item>
         <item>and the</item>
 
         <item>255</item>
-        <item>anothe</item>
-        <item>another</item>
-
-        <item>255</item>
         <item>arent</item>
         <item>aren\'t</item>
 
         <item>255</item>
-        <item>asthe</item>
-        <item>as the</item>
-
-        <item>255</item>
-        <item>atthe</item>
-        <item>at the</item>
-
-        <item>255</item>
-        <item>bakc</item>
-        <item>back</item>
-
-        <item>255</item>
-        <item>beacuse</item>
-        <item>because</item>
-
-        <item>255</item>
-        <item>becasue</item>
-        <item>because</item>
-
-        <item>255</item>
-        <item>becaus</item>
-        <item>because</item>
-
-        <item>255</item>
-        <item>becausea</item>
-        <item>because a</item>
-
-        <item>255</item>
-        <item>becauseof</item>
-        <item>because of</item>
-
-        <item>255</item>
-        <item>becausethe</item>
-        <item>because the</item>
-
-        <item>255</item>
-        <item>becauseyou</item>
-        <item>because you</item>
-
-        <item>255</item>
-        <item>becuase</item>
-        <item>because</item>
-
-        <item>255</item>
-        <item>becuse</item>
-        <item>because</item>
-
-        <item>255</item>
-        <item>beleive</item>
-        <item>believe</item>
-
-        <item>255</item>
         <item>bot</item>
         <item>not</item>
 
@@ -178,126 +63,18 @@
         <item>but</item>
 
         <item>255</item>
-        <item>butthe</item>
-        <item>but the</item>
-
-        <item>255</item>
         <item>cant</item>
         <item>can\'t</item>
 
         <item>255</item>
-        <item>certian</item>
-        <item>certain</item>
-
-        <item>255</item>
-        <item>changable</item>
-        <item>changeable</item>
-
-        <item>255</item>
-        <item>chekc</item>
-        <item>check</item>
-
-        <item>255</item>
-        <item>chnage</item>
-        <item>change</item>
-
-        <item>255</item>
-        <item>couldnt</item>
-        <item>couldn\'t</item>
-
-        <item>255</item>
-        <item>couldthe</item>
-        <item>could the</item>
-
-        <item>255</item>
-        <item>couldve</item>
-        <item>could\'ve</item>
-
-        <item>255</item>
-        <item>cna</item>
-        <item>can</item>
-
-        <item>255</item>
-        <item>committment</item>
-        <item>commitment</item>
-
-        <item>255</item>
-        <item>committments</item>
-        <item>commitments</item>
-
-        <item>255</item>
-        <item>companys</item>
-        <item>company\'s</item>
-
-        <item>255</item>
-        <item>cxan</item>
-        <item>can</item>
-
-        <item>255</item>
         <item>didint</item>
         <item>didn\'t</item>
 
         <item>255</item>
-        <item>didnot</item>
-        <item>did not</item>
-
-        <item>255</item>
-        <item>didnt</item>
-        <item>didn\'t</item>
-
-        <item>255</item>
-        <item>doesnt</item>
-        <item>doesn\'t</item>
-
-        <item>255</item>
-        <item>dont</item>
-        <item>don\'t</item>
-
-        <item>255</item>
-        <item>eyt</item>
-        <item>yet</item>
-
-        <item>255</item>
-        <item>fidn</item>
-        <item>find</item>
-
-        <item>255</item>
         <item>fora</item>
         <item>for a</item>
 
         <item>255</item>
-        <item>freind</item>
-        <item>friend</item>
-
-        <item>255</item>
-        <item>friday</item>
-        <item>Friday</item>
-
-        <item>255</item>
-        <item>hadbeen</item>
-        <item>had been</item>
-
-        <item>255</item>
-        <item>hadnt</item>
-        <item>hadn\'t</item>
-
-        <item>255</item>
-        <item>haev</item>
-        <item>have</item>
-
-        <item>255</item>
-        <item>hasbeen</item>
-        <item>has been</item>
-
-        <item>255</item>
-        <item>hasnt</item>
-        <item>hasn\'t</item>
-
-        <item>255</item>
-        <item>havent</item>
-        <item>haven\'t</item>
-
-        <item>255</item>
         <item>hed</item>
         <item>he\'d</item>
 
@@ -310,14 +87,6 @@
         <item>here\'s</item>
 
         <item>255</item>
-        <item>hes</item>
-        <item>he\'s</item>
-
-        <item>255</item>
-        <item>hlep</item>
-        <item>help</item>
-
-        <item>255</item>
         <item>hoe</item>
         <item>how</item>
 
@@ -342,18 +111,6 @@
         <item>how\'ve</item>
 
         <item>255</item>
-        <item>hte</item>
-        <item>the</item>
-
-        <item>255</item>
-        <item>htis</item>
-        <item>this</item>
-
-        <item>255</item>
-        <item>hvae</item>
-        <item>have</item>
-
-        <item>255</item>
         <item>i</item>
         <item>I</item>
 
@@ -366,50 +123,18 @@
         <item>I\'m</item>
 
         <item>255</item>
-        <item>i\'m</item>
-        <item>I\'m</item>
-
-        <item>255</item>
-        <item>i\'ll</item>
-        <item>I\'ll</item>
-
-        <item>255</item>
-        <item>i\'ve</item>
-        <item>I\'ve</item>
-
-        <item>255</item>
         <item>inteh</item>
         <item>in the</item>
 
         <item>255</item>
-        <item>isnt</item>
-        <item>isn\'t</item>
-
-        <item>255</item>
-        <item>isthe</item>
-        <item>is the</item>
-
-        <item>255</item>
         <item>itd</item>
         <item>it\'d</item>
 
         <item>255</item>
-        <item>itis</item>
-        <item>it is</item>
-
-        <item>255</item>
-        <item>itll</item>
-        <item>it\'ll</item>
-
-        <item>255</item>
         <item>itsa</item>
         <item>it\'s a</item>
 
         <item>255</item>
-        <item>ive</item>
-        <item>I\'ve</item>
-
-        <item>255</item>
         <item>jot</item>
         <item>not</item>
 
@@ -426,217 +151,37 @@
         <item>more</item>
 
         <item>255</item>
-        <item>mkae</item>
-        <item>make</item>
-
-        <item>255</item>
-        <item>mkaes</item>
-        <item>makes</item>
-
-        <item>255</item>
         <item>moat</item>
         <item>most</item>
 
         <item>255</item>
-        <item>monday</item>
-        <item>Monday</item>
-
-        <item>255</item>
         <item>mot</item>
         <item>not</item>
 
         <item>255</item>
-        <item>mustnt</item>
-        <item>mustn\'t</item>
-
-        <item>255</item>
-        <item>neednt</item>
-        <item>needn\'t</item>
-
-        <item>255</item>
         <item>nit</item>
         <item>not</item>
 
         <item>255</item>
-        <item>oclock</item>
-        <item>o\'clock</item>
-
-        <item>255</item>
-        <item>ofits</item>
-        <item>of its</item>
-
-        <item>255</item>
-        <item>ofthe</item>
-        <item>of the</item>
-
-        <item>255</item>
-        <item>omre</item>
-        <item>more</item>
-
-        <item>255</item>
-        <item>oneof</item>
-        <item>one of</item>
-
-        <item>255</item>
         <item>os</item>
         <item>is</item>
 
         <item>255</item>
-        <item>otehr</item>
-        <item>other</item>
-
-        <item>255</item>
-        <item>outof</item>
-        <item>out of</item>
-
-        <item>255</item>
-        <item>overthe</item>
-        <item>over the</item>
-
-        <item>255</item>
-        <item>owrk</item>
-        <item>work</item>
-
-        <item>255</item>
-        <item>percentof</item>
-        <item>percent of</item>
-
-        <item>255</item>
-        <item>recieve</item>
-        <item>receive</item>
-
-        <item>255</item>
-        <item>recieved</item>
-        <item>received</item>
-
-        <item>255</item>
-        <item>recieving</item>
-        <item>receiving</item>
-
-        <item>255</item>
-        <item>saidthat</item>
-        <item>said that</item>
-
-        <item>255</item>
-        <item>saidthe</item>
-        <item>said the</item>
-
-        <item>255</item>
-        <item>saturday</item>
-        <item>Saturday</item>
-
-        <item>255</item>
-        <item>seh</item>
-        <item>she</item>
-
-        <item>255</item>
-        <item>shant</item>
-        <item>shan\'t</item>
-
-        <item>255</item>
-        <item>she\'</item>
-        <item>she\'ll</item>
-
-        <item>255</item>
         <item>shel</item>
         <item>she\'ll</item>
 
         <item>255</item>
-        <item>shes</item>
-        <item>she\'s</item>
-
-        <item>255</item>
         <item>shouldent</item>
         <item>shouldn\'t</item>
 
         <item>255</item>
-        <item>shouldnt</item>
-        <item>shouldn\'t</item>
-
-        <item>255</item>
-        <item>shouldve</item>
-        <item>should\'ve</item>
-
-        <item>255</item>
-        <item>sone</item>
-        <item>some</item>
-
-        <item>255</item>
-        <item>sunday</item>
-        <item>Sunday</item>
-
-        <item>255</item>
-        <item>tahn</item>
-        <item>than</item>
-
-        <item>255</item>
-        <item>taht</item>
-        <item>that</item>
-
-        <item>255</item>
-        <item>teh</item>
-        <item>the</item>
-
-        <item>255</item>
         <item>thatd</item>
         <item>that\'d</item>
 
         <item>255</item>
-        <item>thatll</item>
-        <item>that\'ll</item>
-
-        <item>255</item>
-        <item>thats</item>
-        <item>that\'s</item>
-
-        <item>255</item>
-        <item>thatthe</item>
-        <item>that the</item>
-
-        <item>255</item>
-        <item>theres</item>
-        <item>there\'s</item>
-
-        <item>255</item>
-        <item>theyd</item>
-        <item>they\'d</item>
-
-        <item>255</item>
-        <item>theyll</item>
-        <item>they\'ll</item>
-
-        <item>255</item>
-        <item>theyre</item>
-        <item>they\'re</item>
-
-        <item>255</item>
-        <item>theyve</item>
-        <item>they\'ve</item>
-
-        <item>255</item>
-        <item>thier</item>
-        <item>their</item>
-
-        <item>255</item>
-        <item>thsi</item>
-        <item>this</item>
-
-        <item>255</item>
-        <item>thursday</item>
-        <item>Thursday</item>
-
-        <item>255</item>
         <item>tine</item>
         <item>time</item>
 
-        <item>255</item>
-        <item>tothe</item>
-        <item>to the</item>
-
-        <item>255</item>
-        <item>tuesday</item>
-        <item>Tuesday</item>
-
         <!-- through additional proximity, 'uf' becomes 'of'. 'o' is not next to 'u' so anyone
              typing 'uf' probably meant 'if', but 'of' is much more common and should be left
              higher than 'if', hence the need for this entry. -->
@@ -664,14 +209,6 @@
         <item>vis-a-vis</item>
 
         <item>255</item>
-        <item>wasnt</item>
-        <item>wasn\'t</item>
-
-        <item>255</item>
-        <item>wednesday</item>
-        <item>Wednesday</item>
-
-        <item>255</item>
         <item>wierd</item>
         <item>weird</item>
 
@@ -684,22 +221,10 @@
         <item>we\'re</item>
 
         <item>255</item>
-        <item>werent</item>
-        <item>weren\'t</item>
-
-        <item>255</item>
-        <item>weve</item>
-        <item>we\'ve</item>
-
-        <item>255</item>
         <item>whatd</item>
         <item>what\'d</item>
 
         <item>255</item>
-        <item>whatll</item>
-        <item>what\'ll</item>
-
-        <item>255</item>
         <item>whatm</item>
         <item>what\'m</item>
 
@@ -728,18 +253,10 @@
         <item>where\'s</item>
 
         <item>255</item>
-        <item>whod</item>
-        <item>who\'d</item>
-
-        <item>255</item>
         <item>wholl</item>
         <item>who\'ll</item>
 
         <item>255</item>
-        <item>whos</item>
-        <item>who\'s</item>
-
-        <item>255</item>
         <item>whove</item>
         <item>who\'ve</item>
 
@@ -760,22 +277,10 @@
         <item>why\'ve</item>
 
         <item>255</item>
-        <item>witha</item>
-        <item>with a</item>
-
-        <item>255</item>
         <item>wont</item>
         <item>won\'t</item>
 
         <item>255</item>
-        <item>wouldnt</item>
-        <item>wouldn\'t</item>
-
-        <item>255</item>
-        <item>wouldve</item>
-        <item>would\'ve</item>
-
-        <item>255</item>
         <item>yall</item>
         <item>y\'all</item>
 
@@ -787,16 +292,5 @@
         <item>youd</item>
         <item>you\'d</item>
 
-        <item>255</item>
-        <item>youll</item>
-        <item>you\'ll</item>
-
-        <item>255</item>
-        <item>youre</item>
-        <item>you\'re</item>
-
-        <item>255</item>
-        <item>youve</item>
-        <item>you\'ve</item>
     </string-array>
 </resources>
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
index 67e21b1..3cfef97 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -282,7 +282,12 @@
             return;
         }
 
-        parent.requestSendAccessibilityEvent(mKeyboardView, event);
+        if (!parent.requestSendAccessibilityEvent(mKeyboardView, event)) {
+            // TODO: Remove this line after the top-level view for the IME
+            // window is fixed to be non-null and requestSendAccessibilityEvent
+            // can return true.
+            mAccessibilityUtils.requestSendAccessibilityEvent(event);
+        }
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 2ea7d83..616b1c6 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -174,4 +174,16 @@
             speak(text);
         }
     }
+
+    /**
+     * Sends the specified {@link AccessibilityEvent} if accessibility is
+     * enabled. No operation if accessibility is disabled.
+     *
+     * @param event The event to send.
+     */
+    public void requestSendAccessibilityEvent(AccessibilityEvent event) {
+        if (mAccessibilityManager.isEnabled()) {
+            mAccessibilityManager.sendAccessibilityEvent(event);
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index f4e4105..7e1889a 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -111,9 +111,6 @@
             if (mKeyLabelMap.containsKey(label)) {
                 return context.getString(mKeyLabelMap.get(label));
             }
-
-            // Otherwise, return the label.
-            return key.mLabel;
         }
 
         // Just attempt to speak the description.
@@ -229,6 +226,8 @@
             return context.getString(mKeyCodeMap.get(code));
         } else if (isDefinedNonCtrl) {
             return Character.toString((char) code);
+        } else if (!TextUtils.isEmpty(key.mLabel)) {
+            return key.mLabel;
         } else {
             return context.getString(R.string.spoken_description_unknown, code);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e50d922..37fa674 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -71,7 +71,7 @@
 
     private InputView mCurrentInputView;
     private LatinKeyboardView mKeyboardView;
-    private LatinIME mInputMethodService;
+    private LatinIME mLatinIME;
     private Resources mResources;
 
     private KeyboardState mState;
@@ -95,17 +95,17 @@
         // Intentional empty constructor for singleton.
     }
 
-    public static void init(LatinIME ims, SharedPreferences prefs) {
-        sInstance.initInternal(ims, prefs);
+    public static void init(LatinIME latinIme, SharedPreferences prefs) {
+        sInstance.initInternal(latinIme, prefs);
     }
 
-    private void initInternal(LatinIME ims, SharedPreferences prefs) {
-        mInputMethodService = ims;
-        mResources = ims.getResources();
+    private void initInternal(LatinIME latinIme, SharedPreferences prefs) {
+        mLatinIME = latinIme;
+        mResources = latinIme.getResources();
         mPrefs = prefs;
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mState = new KeyboardState(this);
-        setContextThemeWrapper(ims, getKeyboardTheme(ims, prefs));
+        setContextThemeWrapper(latinIme, getKeyboardTheme(latinIme, prefs));
         mForceNonDistinctMultitouch = prefs.getBoolean(
                 DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false);
     }
@@ -194,14 +194,14 @@
      * Update keyboard shift state triggered by connected EditText status change.
      */
     public void updateShiftState() {
-        mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+        mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
     }
 
     public void onPressKey(int code) {
         if (isVibrateAndSoundFeedbackRequired()) {
-            mInputMethodService.hapticAndAudioFeedback(code);
+            mLatinIME.hapticAndAudioFeedback(code);
         }
-        mState.onPressKey(code);
+        mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
     }
 
     public void onReleaseKey(int code, boolean withSliding) {
@@ -257,7 +257,7 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void requestUpdatingShiftState() {
-        mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+        mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
@@ -311,7 +311,7 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void hapticAndAudioFeedback(int code) {
-        mInputMethodService.hapticAndAudioFeedback(code);
+        mLatinIME.hapticAndAudioFeedback(code);
     }
 
     public void onLongPressTimeout(int code) {
@@ -338,7 +338,7 @@
      * Updates state machine to figure out when to automatically switch back to the previous mode.
      */
     public void onCodeInput(int code) {
-        mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState());
+        mState.onCodeInput(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
     }
 
     public LatinKeyboardView getKeyboardView() {
@@ -354,7 +354,7 @@
         boolean tryGC = true;
         for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
             try {
-                setContextThemeWrapper(mInputMethodService, mKeyboardTheme);
+                setContextThemeWrapper(mLatinIME, mKeyboardTheme);
                 mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
                         R.layout.input_view, null);
                 tryGC = false;
@@ -368,7 +368,7 @@
         }
 
         mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
-        mKeyboardView.setKeyboardActionListener(mInputMethodService);
+        mKeyboardView.setKeyboardActionListener(mLatinIME);
         if (mForceNonDistinctMultitouch) {
             mKeyboardView.setDistinctMultitouch(false);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 2045b0c..51a0f53 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -389,11 +389,6 @@
      * @param keyboard the keyboard to display in this view
      */
     public void setKeyboard(Keyboard keyboard) {
-        // Remove any pending messages.
-        mDrawingHandler.cancelAllMessages();
-        if (mKeyboard != null) {
-            PointerTracker.dismissAllKeyPreviews();
-        }
         mKeyboard = keyboard;
         LatinImeLogger.onSetKeyboard(keyboard);
         requestLayout();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index e3661a9..c85122a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -30,7 +30,7 @@
  * This class contains all keyboard state transition logic.
  *
  * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()},
- * {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)},
+ * {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
  * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
  * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
  *
@@ -297,9 +297,10 @@
         mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
     }
 
-    public void onPressKey(int code) {
+    public void onPressKey(int code, boolean isSinglePointer, int autoCaps) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this);
+            Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
+                   + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
             ResearchLogger.keyboardState_onPressKey(code, this);
@@ -313,6 +314,21 @@
             mSwitchActions.cancelLongPressTimer();
             mShiftKeyState.onOtherKeyPressed();
             mSymbolKeyState.onOtherKeyPressed();
+            // It is required to reset the auto caps state when all of the following conditions
+            // are met:
+            // 1) two or more fingers are in action
+            // 2) in alphabet layout
+            // 3) not in all characters caps mode
+            // As for #3, please note that it's required to check even when the auto caps mode is
+            // off because, for example, we may be in the #1 state within the manual temporary
+            // shifted mode.
+            if (!isSinglePointer && mIsAlphabetMode && autoCaps != TextUtils.CAP_MODE_CHARACTERS) {
+                final boolean needsToResetAutoCaps = mAlphabetShiftState.isAutomaticShifted()
+                        || (mAlphabetShiftState.isManualShifted() && mShiftKeyState.isReleasing());
+                if (needsToResetAutoCaps) {
+                    mSwitchActions.setAlphabetKeyboard();
+                }
+            }
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 22787c2..0a09c84 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -60,7 +60,7 @@
     private final boolean mUseFirstLastBigrams;
 
     public ContactsBinaryDictionary(final Context context, final int dicTypeId, Locale locale) {
-        super(context, getFilenameWithLocale(locale), dicTypeId);
+        super(context, getFilenameWithLocale(NAME, locale.toString()), dicTypeId);
         mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
         registerObserver(context);
 
@@ -69,10 +69,6 @@
         loadDictionary();
     }
 
-    private static String getFilenameWithLocale(Locale locale) {
-        return NAME + "." + locale.toString() + ".dict";
-    }
-
     private synchronized void registerObserver(final Context context) {
         // Perform a managed query. The Activity will handle closing and requerying the cursor
         // when needed.
@@ -153,7 +149,11 @@
         final Cursor cursor = mContext.getContentResolver().query(
                 Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null);
         if (cursor != null) {
-            return cursor.getCount();
+            try {
+                return cursor.getCount();
+            } finally {
+                cursor.close();
+            }
         }
         return 0;
     }
@@ -175,7 +175,7 @@
                 // capitalization of i.
                 final int wordLen = word.codePointCount(0, word.length());
                 if (wordLen < MAX_WORD_LENGTH && wordLen > 1) {
-                    super.addWord(word, FREQUENCY_FOR_CONTACTS);
+                    super.addWord(word, null /* shortcut */, FREQUENCY_FOR_CONTACTS);
                     if (!TextUtils.isEmpty(prevWord)) {
                         if (mUseFirstLastBigrams) {
                             super.setBigram(prevWord, word, FREQUENCY_FOR_CONTACTS_BIGRAM);
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
index 83bc904..2f33952 100644
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
@@ -28,6 +28,12 @@
 
 import com.android.inputmethod.keyboard.Keyboard;
 
+// TODO: This class is superseded by {@link ContactsBinaryDictionary}. Should be cleaned up.
+/**
+ * An expandable dictionary that stores the words from Contacts provider.
+ *
+ * @deprecated Use {@link ContactsBinaryDictionary}.
+ */
 public class ContactsDictionary extends ExpandableDictionary {
 
     private static final String[] PROJECTION = {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 22d8f24..08f5854 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -22,11 +22,13 @@
 import com.android.inputmethod.latin.makedict.BinaryDictInputOutput;
 import com.android.inputmethod.latin.makedict.FusionDictionary;
 import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
+import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -133,6 +135,10 @@
         clearFusionDictionary();
     }
 
+    protected static String getFilenameWithLocale(final String name, final String localeStr) {
+        return name + "." + localeStr + ".dict";
+    }
+
     /**
      * Closes and cleans up the binary dictionary.
      */
@@ -166,8 +172,15 @@
      */
     // TODO: Create "cache dictionary" to cache fresh words for frequently updated dictionaries,
     // considering performance regression.
-    protected void addWord(final String word, final int frequency) {
-        mFusionDictionary.add(word, frequency, null /* shortcutTargets */);
+    protected void addWord(final String word, final String shortcutTarget, final int frequency) {
+        if (shortcutTarget == null) {
+            mFusionDictionary.add(word, frequency, null);
+        } else {
+            // TODO: Do this in the subclass, with this class taking an arraylist.
+            final ArrayList<WeightedString> shortcutTargets = new ArrayList<WeightedString>();
+            shortcutTargets.add(new WeightedString(shortcutTarget, frequency));
+            mFusionDictionary.add(word, frequency, shortcutTargets);
+        }
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index b632d34..b474a85 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -106,6 +106,9 @@
     /** Whether to use the binary version of the contacts dictionary */
     public static final boolean USE_BINARY_CONTACTS_DICTIONARY = true;
 
+    /** Whether to use the binary version of the user dictionary */
+    public static final boolean USE_BINARY_USER_DICTIONARY = true;
+
     // TODO: migrate this to SettingsValues
     private int mSuggestionVisibility;
     private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
@@ -158,7 +161,8 @@
     private boolean mShouldSwitchToLastSubtype = true;
 
     private boolean mIsMainDictionaryAvailable;
-    private UserDictionary mUserDictionary;
+    // TODO: revert this back to the concrete class after transition.
+    private Dictionary mUserDictionary;
     private UserHistoryDictionary mUserHistoryDictionary;
     private boolean mIsUserDictionaryAvailable;
 
@@ -476,9 +480,14 @@
 
         mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
 
-        mUserDictionary = new UserDictionary(this, localeStr);
+        if (USE_BINARY_USER_DICTIONARY) {
+            mUserDictionary = new UserBinaryDictionary(this, localeStr);
+            mIsUserDictionaryAvailable = ((UserBinaryDictionary)mUserDictionary).isEnabled();
+        } else {
+            mUserDictionary = new UserDictionary(this, localeStr);
+            mIsUserDictionaryAvailable = ((UserDictionary)mUserDictionary).isEnabled();
+        }
         mSuggest.setUserDictionary(mUserDictionary);
-        mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
 
         resetContactsDictionary(oldContactsDictionary);
 
@@ -1047,6 +1056,10 @@
                 | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
         if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF;
 
+        // Avoid making heavy round-trip IPC calls of {@link InputConnection#getCursorCapsMode}
+        // unless needed.
+        if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF;
+
         final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return Constants.TextUtils.CAP_MODE_OFF;
         // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
@@ -1123,7 +1136,11 @@
 
     @Override
     public boolean addWordToDictionary(String word) {
-        mUserDictionary.addWordToUserDictionary(word, 128);
+        if (USE_BINARY_USER_DICTIONARY) {
+            ((UserBinaryDictionary)mUserDictionary).addWordToUserDictionary(word, 128);
+        } else {
+            ((UserDictionary)mUserDictionary).addWordToUserDictionary(word, 128);
+        }
         // Suggestion strip should be updated after the operation of adding word to the
         // user dictionary
         mHandler.postUpdateSuggestions();
@@ -1141,7 +1158,6 @@
 
     // Virtual codes representing custom requests.  These are used in onCustomRequest() below.
     public static final int CODE_SHOW_INPUT_METHOD_PICKER = 1;
-    public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK = 2;
 
     @Override
     public boolean onCustomRequest(int requestCode) {
@@ -1154,9 +1170,6 @@
                 return true;
             }
             return false;
-        case CODE_HAPTIC_AND_AUDIO_FEEDBACK:
-            hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED);
-            return true;
         }
         return false;
     }
@@ -2252,6 +2265,8 @@
         }
     }
 
+    // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to
+    // {@link KeyboardSwitcher}.
     public void hapticAndAudioFeedback(final int primaryCode) {
         mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView());
     }
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 188259f..4994e59 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -26,7 +26,6 @@
     public SynchronouslyLoadedContactsBinaryDictionary(final Context context) {
         // TODO: add locale information.
         super(context, Suggest.DIC_CONTACTS, null);
-        mClosed = false;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
new file mode 100644
index 0000000..1606a34
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+
+import com.android.inputmethod.keyboard.ProximityInfo;
+
+public class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDictionary {
+
+    public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale) {
+        this(context, locale, false);
+    }
+
+    public SynchronouslyLoadedUserBinaryDictionary(final Context context, final String locale,
+            final boolean alsoUseMoreRestrictiveLocales) {
+        super(context, locale, alsoUseMoreRestrictiveLocales);
+    }
+
+    @Override
+    public synchronized void getWords(final WordComposer codes,
+            final CharSequence prevWordForBigrams, final WordCallback callback,
+            final ProximityInfo proximityInfo) {
+        syncReloadDictionaryIfRequired();
+        getWordsInner(codes, prevWordForBigrams, callback, proximityInfo);
+    }
+
+    @Override
+    public synchronized boolean isValidWord(CharSequence word) {
+        syncReloadDictionaryIfRequired();
+        return isValidWordInner(word);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
index b78be89..23a49c1 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
@@ -21,6 +21,7 @@
 import com.android.inputmethod.keyboard.ProximityInfo;
 
 public class SynchronouslyLoadedUserDictionary extends UserDictionary {
+    private boolean mClosed;
 
     public SynchronouslyLoadedUserDictionary(final Context context, final String locale) {
         this(context, locale, false);
@@ -44,4 +45,12 @@
         blockingReloadDictionaryIfRequired();
         return super.isValidWord(word);
     }
+
+    // Protect against multiple closing
+    @Override
+    public synchronized void close() {
+        if (mClosed) return;
+        mClosed = true;
+        super.close();
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
new file mode 100644
index 0000000..6fa1a25
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.provider.UserDictionary.Words;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+
+/**
+ * An expandable dictionary that stores the words in the user unigram dictionary.
+ *
+ * Largely a copy of UserDictionary, will replace that class in the future.
+ */
+public class UserBinaryDictionary extends ExpandableBinaryDictionary {
+
+    // TODO: use Words.SHORTCUT when it's public in the SDK
+    final static String SHORTCUT = "shortcut";
+    private static final String[] PROJECTION_QUERY = {
+        Words.WORD,
+        SHORTCUT,
+        Words.FREQUENCY,
+    };
+
+    private static final String NAME = "userunigram";
+
+    // This is not exported by the framework so we pretty much have to write it here verbatim
+    private static final String ACTION_USER_DICTIONARY_INSERT =
+            "com.android.settings.USER_DICTIONARY_INSERT";
+
+    private ContentObserver mObserver;
+    final private String mLocale;
+    final private boolean mAlsoUseMoreRestrictiveLocales;
+
+    public UserBinaryDictionary(final Context context, final String locale) {
+        this(context, locale, false);
+    }
+
+    public UserBinaryDictionary(final Context context, final String locale,
+            final boolean alsoUseMoreRestrictiveLocales) {
+        super(context, getFilenameWithLocale(NAME, locale), Suggest.DIC_USER);
+        if (null == locale) throw new NullPointerException(); // Catch the error earlier
+        mLocale = locale;
+        mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
+        // Perform a managed query. The Activity will handle closing and re-querying the cursor
+        // when needed.
+        ContentResolver cres = context.getContentResolver();
+
+        mObserver = new ContentObserver(null) {
+            @Override
+            public void onChange(boolean self) {
+                setRequiresReload(true);
+            }
+        };
+        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
+
+        loadDictionary();
+    }
+
+    @Override
+    public synchronized void close() {
+        if (mObserver != null) {
+            mContext.getContentResolver().unregisterContentObserver(mObserver);
+            mObserver = null;
+        }
+        super.close();
+    }
+
+    @Override
+    public void loadDictionaryAsync() {
+        // Split the locale. For example "en" => ["en"], "de_DE" => ["de", "DE"],
+        // "en_US_foo_bar_qux" => ["en", "US", "foo_bar_qux"] because of the limit of 3.
+        // This is correct for locale processing.
+        // For this example, we'll look at the "en_US_POSIX" case.
+        final String[] localeElements =
+                TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
+        final int length = localeElements.length;
+
+        final StringBuilder request = new StringBuilder("(locale is NULL)");
+        String localeSoFar = "";
+        // At start, localeElements = ["en", "US", "POSIX"] ; localeSoFar = "" ;
+        // and request = "(locale is NULL)"
+        for (int i = 0; i < length; ++i) {
+            // i | localeSoFar    | localeElements
+            // 0 | ""             | ["en", "US", "POSIX"]
+            // 1 | "en_"          | ["en", "US", "POSIX"]
+            // 2 | "en_US_"       | ["en", "en_US", "POSIX"]
+            localeElements[i] = localeSoFar + localeElements[i];
+            localeSoFar = localeElements[i] + "_";
+            // i | request
+            // 0 | "(locale is NULL)"
+            // 1 | "(locale is NULL) or (locale=?)"
+            // 2 | "(locale is NULL) or (locale=?) or (locale=?)"
+            request.append(" or (locale=?)");
+        }
+        // At the end, localeElements = ["en", "en_US", "en_US_POSIX"]; localeSoFar = en_US_POSIX_"
+        // and request = "(locale is NULL) or (locale=?) or (locale=?) or (locale=?)"
+
+        final String[] requestArguments;
+        // If length == 3, we already have all the arguments we need (common prefix is meaningless
+        // inside variants
+        if (mAlsoUseMoreRestrictiveLocales && length < 3) {
+            request.append(" or (locale like ?)");
+            // The following creates an array with one more (null) position
+            final String[] localeElementsWithMoreRestrictiveLocalesIncluded =
+                    Arrays.copyOf(localeElements, length + 1);
+            localeElementsWithMoreRestrictiveLocalesIncluded[length] =
+                    localeElements[length - 1] + "_%";
+            requestArguments = localeElementsWithMoreRestrictiveLocalesIncluded;
+            // If for example localeElements = ["en"]
+            // then requestArguments = ["en", "en_%"]
+            // and request = (locale is NULL) or (locale=?) or (locale like ?)
+            // If localeElements = ["en", "en_US"]
+            // then requestArguments = ["en", "en_US", "en_US_%"]
+        } else {
+            requestArguments = localeElements;
+        }
+        final Cursor cursor = mContext.getContentResolver().query(
+            Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null);
+        try {
+            addWords(cursor);
+        } finally {
+            if (null != cursor) cursor.close();
+        }
+    }
+
+    public boolean isEnabled() {
+        final ContentResolver cr = mContext.getContentResolver();
+        final ContentProviderClient client = cr.acquireContentProviderClient(Words.CONTENT_URI);
+        if (client != null) {
+            client.release();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Adds a word to the user dictionary and makes it persistent.
+     *
+     * This will call upon the system interface to do the actual work through the intent readied by
+     * the system to this effect.
+     *
+     * @param word the word to add. If the word is capitalized, then the dictionary will
+     * recognize it as a capitalized word when searched.
+     * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered
+     * the highest.
+     * @TODO use a higher or float range for frequency
+     */
+    public synchronized void addWordToUserDictionary(final String word, final int frequency) {
+        // TODO: do something for the UI. With the following, any sufficiently long word will
+        // look like it will go to the user dictionary but it won't.
+        // Safeguard against adding long words. Can cause stack overflow.
+        if (word.length() >= MAX_WORD_LENGTH) return;
+
+        // TODO: Add an argument to the intent to specify the frequency.
+        Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
+        intent.putExtra(Words.WORD, word);
+        intent.putExtra(Words.LOCALE, mLocale);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    private void addWords(Cursor cursor) {
+        clearFusionDictionary();
+        if (cursor == null) return;
+        if (cursor.moveToFirst()) {
+            final int indexWord = cursor.getColumnIndex(Words.WORD);
+            final int indexShortcut = cursor.getColumnIndex(SHORTCUT);
+            final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
+            while (!cursor.isAfterLast()) {
+                String word = cursor.getString(indexWord);
+                String shortcut = cursor.getString(indexShortcut);
+                int frequency = cursor.getInt(indexFrequency);
+                // Safeguard against adding really long words.
+                if (word.length() < MAX_WORD_LENGTH) {
+                    super.addWord(word, null, frequency);
+                }
+                if (null != shortcut && shortcut.length() < MAX_WORD_LENGTH) {
+                    super.addWord(shortcut, word, frequency);
+                }
+                cursor.moveToNext();
+            }
+        }
+    }
+
+    @Override
+    protected boolean hasContentChanged() {
+        return true;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 218bac7..81e2fdc 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -29,6 +29,12 @@
 
 import java.util.Arrays;
 
+// TODO: This class is superseded by {@link UserBinaryDictionary}. Should be cleaned up.
+/**
+ * An expandable dictionary that stores the words in the user unigram dictionary.
+ *
+ * @deprecated Use {@link UserBinaryDictionary}.
+ */
 public class UserDictionary extends ExpandableDictionary {
 
     // TODO: use Words.SHORTCUT when it's public in the SDK
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index d7c8e38..9807d28 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -40,6 +40,7 @@
 import com.android.inputmethod.latin.StringUtils;
 import com.android.inputmethod.latin.SynchronouslyLoadedContactsBinaryDictionary;
 import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary;
+import com.android.inputmethod.latin.SynchronouslyLoadedUserBinaryDictionary;
 import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary;
 import com.android.inputmethod.latin.WhitelistDictionary;
 import com.android.inputmethod.latin.WordComposer;
@@ -403,7 +404,11 @@
         final String localeStr = locale.toString();
         Dictionary userDictionary = mUserDictionaries.get(localeStr);
         if (null == userDictionary) {
-            userDictionary = new SynchronouslyLoadedUserDictionary(this, localeStr, true);
+            if (LatinIME.USE_BINARY_USER_DICTIONARY) {
+                userDictionary = new SynchronouslyLoadedUserBinaryDictionary(this, localeStr, true);
+            } else {
+                userDictionary = new SynchronouslyLoadedUserDictionary(this, localeStr, true);
+            }
             mUserDictionaries.put(localeStr, userDictionary);
         }
         dictionaryCollection.addDictionary(userDictionary);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
index 26a9415..3d593aa 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java
@@ -596,7 +596,7 @@
     }
 
     /**
-     * Construct a {@link SuggestionsView} for showing suggested words for completion.
+     * Construct a {@link SuggestionsView} for showing suggestions to be picked by the user.
      * @param context
      * @param attrs
      */
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
index c2408c9..dc098db 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
@@ -34,6 +34,26 @@
         releaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED);
     }
 
+    // Chording input in shifted.
+    public void testChordingShifted() {
+        // Press shift key, enter alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+
+        // Press shift key and hold, enter into choring shift state.
+        pressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+        // Press/release letter key.
+        chordingPressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+        // Release shift key, switch back to alphabet shifted.
+        releaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+
+        // Press "?123" key and hold, enter into choring symbols state.
+        pressKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED);
+        // Press/release symbol letter key.
+        chordingPressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED);
+        // Release "123?" key, switch back to alphabet shift unshifted.
+        releaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED);
+    }
+
     // Chording input in shift locked.
     public void testChordingShiftLocked() {
         // Long press shift key, enter alphabet shift locked.
@@ -240,4 +260,114 @@
         // Release shift key
         releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED);
     }
+
+    // Multi touch input in manual shifted.
+    public void testMultiTouchManualShifted() {
+        // Press/release shift key, enter into alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+
+        // Press 'X' key and hold
+        pressKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Press 'z' key and hold, switch back to alphabet unshifted.
+        chordingPressKey('z', ALPHABET_UNSHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_UNSHIFTED);
+        // Release 'z' key
+        releaseKey('z', ALPHABET_UNSHIFTED);
+    }
+
+    // Multi touch input in automatic upper case.
+    public void testMultiTouchAutomaticUpperCase() {
+        // Set auto word caps mode on.
+        setAutoCapsMode(CAP_MODE_WORDS);
+        // Update shift state with auto caps enabled.
+        pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
+
+        // Press 'X' key and hold
+        pressKey('X', ALPHABET_AUTOMATIC_SHIFTED);
+        // Press 'z' key and hold, switch back to alphabet unshifted.
+        chordingPressKey('z', ALPHABET_UNSHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_UNSHIFTED);
+        // Release 'z' key
+        releaseKey('z', ALPHABET_UNSHIFTED);
+    }
+
+    // Multi touch input in capitalize character mode.
+    public void testMultiTouchCapModeCharacter() {
+        // Set auto character caps mode on.
+        setAutoCapsMode(CAP_MODE_CHARACTERS);
+        // Update shift state with auto caps enabled.
+        pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
+
+        // Press 'X' key and hold
+        pressKey('X', ALPHABET_AUTOMATIC_SHIFTED);
+        // Press 'Z' key and hold, stay in automatic shifted mode.
+        chordingPressKey('Z', ALPHABET_AUTOMATIC_SHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_AUTOMATIC_SHIFTED);
+        // Release 'Z' key
+        releaseKey('Z', ALPHABET_AUTOMATIC_SHIFTED);
+    }
+
+    // Multi touch shift chording input in manual shifted.
+    public void testMultiTouchShiftChordingManualShifted() {
+        // Press/release shift key, enter into alphabet shifted.
+        pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED);
+
+        // Press shift key and hold, stays in alphabet shifted.
+        pressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+        // Press 'X' key and hold
+        chordingPressKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Press 'Z' key and hold, stays in alphabet shifted.
+        chordingPressKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Release 'Z' key
+        releaseKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release shift key.
+        releaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+    }
+
+    // Multi touch shift chording input in automatic upper case.
+    public void testMultiTouchShiftChordingAutomaticUpperCase() {
+        // Set auto word caps mode on.
+        setAutoCapsMode(CAP_MODE_WORDS);
+        // Update shift state with auto caps enabled.
+        pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
+
+        // Press shift key and hold, switch to alphabet shifted.
+        pressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+        // Press 'X' key and hold
+        chordingPressKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Press 'Z' key and hold, stays in alphabet shifted.
+        chordingPressKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Release 'Z' key
+        releaseKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release shift key.
+        releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED);
+    }
+
+    // Multi touch shift chording input in capitalize character mode.
+    public void testMultiTouchShiftChordingCapModeCharacter() {
+        // Set auto character caps mode on.
+        setAutoCapsMode(CAP_MODE_CHARACTERS);
+        // Update shift state with auto caps enabled.
+        pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
+
+        // Press shift key and hold, switch to alphabet shifted.
+        pressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED);
+        // Press 'X' key and hold
+        chordingPressKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Press 'Z' key and hold, stay in automatic shifted mode.
+        chordingPressKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_MANUAL_SHIFTED);
+        // Release 'Z' key
+        releaseKey('Z', ALPHABET_MANUAL_SHIFTED);
+        // Release shift key.
+        releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED);
+    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index bbe0dbd..9472a1f 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -64,14 +64,14 @@
         assertLayout(afterRotate, mSwitcher.getLayoutId());
     }
 
-    private void pressKeyWithoutTimerExpire(int code, int afterPress) {
-        mSwitcher.onPressKey(code);
+    private void pressKeyWithoutTimerExpire(int code, boolean isSinglePointer, int afterPress) {
+        mSwitcher.onPressKey(code, isSinglePointer);
         assertLayout(afterPress, mSwitcher.getLayoutId());
     }
 
     public void pressKey(int code, int afterPress) {
         mSwitcher.expireDoubleTapTimeout();
-        pressKeyWithoutTimerExpire(code, afterPress);
+        pressKeyWithoutTimerExpire(code, true, afterPress);
     }
 
     public void releaseKey(int code, int afterRelease) {
@@ -86,7 +86,8 @@
     }
 
     public void chordingPressKey(int code, int afterPress) {
-        pressKey(code, afterPress);
+        mSwitcher.expireDoubleTapTimeout();
+        pressKeyWithoutTimerExpire(code, false, afterPress);
     }
 
     public void chordingReleaseKey(int code, int afterRelease) {
@@ -114,7 +115,7 @@
     }
 
     public void secondPressAndReleaseKey(int code, int afterPress, int afterRelease) {
-        pressKeyWithoutTimerExpire(code, afterPress);
+        pressKeyWithoutTimerExpire(code, true, afterPress);
         releaseKey(code, afterRelease);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index 485ea61..dd4caad 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -174,8 +174,8 @@
         mState.onSaveKeyboardState();
     }
 
-    public void onPressKey(int code) {
-        mState.onPressKey(code);
+    public void onPressKey(int code, boolean isSinglePointer) {
+        mState.onPressKey(code, isSinglePointer, mAutoCapsState);
     }
 
     public void onReleaseKey(int code, boolean withSliding) {