aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/raw/main_en.dictbin1069228 -> 1069229 bytes
-rw-r--r--java/res/raw/main_fr.dictbin1330249 -> 1328417 bytes
-rw-r--r--java/res/values-en/whitelist.xml513
-rw-r--r--java/res/values-sw600dp/dimens.xml1
-rw-r--r--java/res/values-sw768dp/dimens.xml1
-rw-r--r--java/res/values/attrs.xml5
-rw-r--r--java/res/values/dimens.xml1
-rw-r--r--java/res/values/strings.xml14
-rw-r--r--java/res/values/styles.xml1
-rw-r--r--java/res/xml-sw600dp/key_styles_common.xml9
-rw-r--r--java/res/xml/key_styles_number.xml9
-rw-r--r--java/res/xml/rows_number_normal.xml2
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java7
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java12
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java2
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java26
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java30
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java12
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java37
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java15
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java8
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java17
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java60
-rw-r--r--java/src/com/android/inputmethod/latin/ResearchLogger.java2
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java1
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java47
-rw-r--r--java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java9
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java211
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java6
-rw-r--r--java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java120
-rw-r--r--java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java7
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java2
34 files changed, 605 insertions, 593 deletions
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index 2cfa35168..f544da61a 100644
--- a/java/res/raw/main_en.dict
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index cfa9f473d..084ef7c10 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/values-en/whitelist.xml b/java/res/values-en/whitelist.xml
index bcb884e1d..29a828c7e 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,42 @@
<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>
+ <!-- TODO: Remove this entry after "yes" gets bumped up in the dictionary. -->
<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>tes</item>
+ <item>yes</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 +214,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 +226,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 +258,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 +282,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 +297,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/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml
index 8ecdffb47..5596ba41c 100644
--- a/java/res/values-sw600dp/dimens.xml
+++ b/java/res/values-sw600dp/dimens.xml
@@ -57,6 +57,7 @@
<fraction name="key_letter_ratio">42%</fraction>
<fraction name="key_large_letter_ratio">45%</fraction>
<fraction name="key_label_ratio">25%</fraction>
+ <fraction name="key_large_label_ratio">32%</fraction>
<fraction name="key_hint_letter_ratio">23%</fraction>
<fraction name="key_hint_label_ratio">28%</fraction>
<fraction name="key_uppercase_letter_ratio">22%</fraction>
diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml
index 01e228499..ce33b73cb 100644
--- a/java/res/values-sw768dp/dimens.xml
+++ b/java/res/values-sw768dp/dimens.xml
@@ -58,6 +58,7 @@
<fraction name="key_letter_ratio">40%</fraction>
<fraction name="key_large_letter_ratio">42%</fraction>
<fraction name="key_label_ratio">28%</fraction>
+ <fraction name="key_large_label_ratio">28%</fraction>
<fraction name="key_hint_letter_ratio">23%</fraction>
<fraction name="key_hint_label_ratio">28%</fraction>
<fraction name="key_uppercase_letter_ratio">26%</fraction>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 7cad3f507..a18371fc9 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -55,6 +55,8 @@
<attr name="keyLargeLetterRatio" format="float" />
<!-- Size of the text for keys with multiple letters, in the proportion of key height. -->
<attr name="keyLabelRatio" format="float" />
+ <!-- Large size of the text for keys with multiple letters, in the proportion of key height. -->
+ <attr name="keyLargeLabelRatio" format="float" />
<!-- Size of the text for hint letter (= one character hint label), in the proportion of
key height. -->
<attr name="keyHintLetterRatio" format="float" />
@@ -275,7 +277,8 @@
<flag name="followKeyLargeLetterRatio" value="0x40" />
<flag name="followKeyLetterRatio" value="0x80" />
<flag name="followKeyLabelRatio" value="0xC0" />
- <flag name="followKeyHintLabelRatio" value="0x100" />
+ <flag name="followKeyLargeLabelRatio" value="0x100" />
+ <flag name="followKeyHintLabelRatio" value="0x140" />
<flag name="hasPopupHint" value="0x200" />
<flag name="hasShiftedLetterHint" value="0x400" />
<flag name="hasHintLabel" value="0x800" />
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index d8d58dfa0..925eb55fa 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -59,6 +59,7 @@
<fraction name="key_letter_ratio">55%</fraction>
<fraction name="key_large_letter_ratio">65%</fraction>
<fraction name="key_label_ratio">34%</fraction>
+ <fraction name="key_large_label_ratio">40%</fraction>
<fraction name="key_hint_letter_ratio">25%</fraction>
<fraction name="key_hint_label_ratio">44%</fraction>
<fraction name="key_uppercase_letter_ratio">35%</fraction>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index b9bec9896..e1f03714a 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -277,21 +277,21 @@
<string name="custom_input_styles_title">Custom input styles</string>
<!-- Title of the option menu to add a new style entry in the preference settings [CHAR LIMIT=16] -->
<string name="add_style">Add style</string>
- <!-- Title of the button to add custom style entry in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the button to add custom style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="add">Add</string>
- <!-- Title of the button to remove a custom style entry in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the button to remove a custom style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="remove">Remove</string>
- <!-- Title of the button to save a custom style entry in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the button to save a custom style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="save">Save</string>
- <!-- Title of the spinner for choosing a language of custom style in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the spinner for choosing a language of custom style in the settings dialog [CHAR LIMIT=15] -->
<string name="subtype_locale">Language</string>
- <!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR LIMIT=15] -->
<string name="keyboard_layout_set">Layout</string>
<!-- The message of the dialog to note that a custom input style needs to be enabled. [CHAR LIMIT=64] -->
<string name="custom_input_style_note_message">"Your custom input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
- <!-- Title of the button to enable a custom input style entry in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the button to enable a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="enable">Enable</string>
- <!-- Title of the button to postpone enabling a custom input style entry in the settings dialog [CHAR LIMIT=12] -->
+ <!-- Title of the button to postpone enabling a custom input style entry in the settings dialog [CHAR LIMIT=15] -->
<string name="not_now">Not now</string>
<!-- Toast text to describe the same input style already exists [CHAR LIMIT=64]-->
<string name="custom_input_style_already_exists">"The same input style already exists: <xliff:g id="input_style_name">%s</xliff:g>"</string>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index b3c921e9e..e9b0470ea 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -38,6 +38,7 @@
<item name="keyLetterRatio">@fraction/key_letter_ratio</item>
<item name="keyLargeLetterRatio">@fraction/key_large_letter_ratio</item>
<item name="keyLabelRatio">@fraction/key_label_ratio</item>
+ <item name="keyLargeLabelRatio">@fraction/key_large_label_ratio</item>
<item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item>
<item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item>
<item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index 5b3d1b835..a1b2eb475 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -74,6 +74,15 @@
latin:backgroundType="functional" />
<include
latin:keyboardLayout="@xml/key_styles_enter" />
+ <!-- Override defaultEnterKeyStyle in key_styles_enter.xml -->
+ <key-style
+ latin:styleName="defaultEnterKeyStyle"
+ latin:code="!code/key_enter"
+ latin:keyIcon="!icon/enter_key"
+ latin:keyLabelFlags="preserveCase|autoXScale|followKeyLargeLabelRatio"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional"
+ latin:parentStyle="navigateMoreKeysStyle" />
<key-style
latin:styleName="spaceKeyStyle"
latin:code="!code/key_space"
diff --git a/java/res/xml/key_styles_number.xml b/java/res/xml/key_styles_number.xml
index b8301bc49..2e5a601b0 100644
--- a/java/res/xml/key_styles_number.xml
+++ b/java/res/xml/key_styles_number.xml
@@ -131,4 +131,13 @@
latin:keyIcon="!icon/space_key_for_number_layout"
latin:keyActionFlags="enableLongPress"
latin:parentStyle="numKeyBaseStyle" />
+ <!-- Override defaultEnterKeyStyle in key_styles_enter.xml -->
+ <key-style
+ latin:styleName="defaultEnterKeyStyle"
+ latin:code="!code/key_enter"
+ latin:keyIcon="!icon/enter_key"
+ latin:keyLabelFlags="preserveCase|autoXScale|followKeyLargeLabelRatio"
+ latin:keyActionFlags="noKeyPreview"
+ latin:backgroundType="functional"
+ latin:parentStyle="navigateMoreKeysStyle" />
</merge>
diff --git a/java/res/xml/rows_number_normal.xml b/java/res/xml/rows_number_normal.xml
index 28bd7a1d2..c59e26247 100644
--- a/java/res/xml/rows_number_normal.xml
+++ b/java/res/xml/rows_number_normal.xml
@@ -22,7 +22,7 @@
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<Row>
-<Key
+ <Key
latin:keyLabel="1"
latin:keyStyle="numKeyStyle" />
<Key
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
index 67e21b10c..3cfef972a 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java
@@ -282,7 +282,12 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat
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 2ea7d83e4..616b1c6d7 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -174,4 +174,16 @@ public class AccessibilityUtils {
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/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index 1b0e488bc..2623dcc03 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -113,7 +113,7 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat {
case MotionEvent.ACTION_HOVER_EXIT:
// Make sure we're not getting an EXIT event because the user slid
// off the keyboard area, then force a key press.
- if (pointInView(x, y)) {
+ if (pointInView(x, y) && (key != null)) {
getAccessibilityNodeProvider().simulateKeyPress(key);
}
//$FALL-THROUGH$
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index f4e4105e3..7e1889a74 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -111,9 +111,6 @@ public class KeyCodeDescriptionMapper {
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 @@ public class KeyCodeDescriptionMapper {
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/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index c3f5e7da2..45ed34ed2 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -66,11 +66,14 @@ public class Key {
private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08;
private static final int LABEL_FLAGS_FONT_NORMAL = 0x10;
private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x20;
- private static final int LABEL_FLAGS_FOLLOW_KEY_RATIO_MASK = 0x1C0;
+ // Start of key text ratio enum values
+ private static final int LABEL_FLAGS_FOLLOW_KEY_TEXT_RATIO_MASK = 0x1C0;
private static final int LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO = 0x40;
private static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80;
private static final int LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO = 0xC0;
- private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_LARGE_LABEL_RATIO = 0x100;
+ private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x140;
+ // End of key text ratio mask enum values
private static final int LABEL_FLAGS_HAS_POPUP_HINT = 0x200;
private static final int LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT = 0x400;
private static final int LABEL_FLAGS_HAS_HINT_LABEL = 0x800;
@@ -490,18 +493,21 @@ public class Key {
}
}
- public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) {
- switch (mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_RATIO_MASK) {
- case LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO:
- return largeLetter;
+ public int selectTextSize(int letterSize, int largeLetterSize, int labelSize,
+ int largeLabelSize, int hintLabelSize) {
+ switch (mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_TEXT_RATIO_MASK) {
case LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO:
- return letter;
+ return letterSize;
+ case LABEL_FLAGS_FOLLOW_KEY_LARGE_LETTER_RATIO:
+ return largeLetterSize;
case LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO:
- return label;
+ return labelSize;
+ case LABEL_FLAGS_FOLLOW_KEY_LARGE_LABEL_RATIO:
+ return largeLabelSize;
case LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO:
- return hintLabel;
+ return hintLabelSize;
default: // No follow key ratio flag specified.
- return StringUtils.codePointCount(mLabel) == 1 ? letter : label;
+ return StringUtils.codePointCount(mLabel) == 1 ? letterSize : labelSize;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e50d922ea..37fa674c2 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -71,7 +71,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
private InputView mCurrentInputView;
private LatinKeyboardView mKeyboardView;
- private LatinIME mInputMethodService;
+ private LatinIME mLatinIME;
private Resources mResources;
private KeyboardState mState;
@@ -95,17 +95,17 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
// 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 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
* 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 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void requestUpdatingShiftState() {
- mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+ mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
}
// Implements {@link KeyboardState.SwitchActions}.
@@ -311,7 +311,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
// 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 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
* 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 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
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 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
}
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 cc0a1fb10..51a0f537f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -191,6 +191,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
/* package */ final float mKeyLetterRatio;
private final float mKeyLargeLetterRatio;
private final float mKeyLabelRatio;
+ private final float mKeyLargeLabelRatio;
private final float mKeyHintLetterRatio;
private final float mKeyShiftedLetterHintRatio;
private final float mKeyHintLabelRatio;
@@ -200,6 +201,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
public int mKeyLetterSize;
public int mKeyLargeLetterSize;
public int mKeyLabelSize;
+ public int mKeyLargeLabelSize;
public int mKeyHintLetterSize;
public int mKeyShiftedLetterHintSize;
public int mKeyHintLabelSize;
@@ -219,6 +221,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
} else {
mKeyLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLabelRatio);
}
+ mKeyLargeLabelRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLabelRatio);
mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio);
mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio);
mKeyShiftedLetterHintRatio = getRatio(a,
@@ -254,6 +257,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mKeyLetterSize = (int)(keyHeight * mKeyLetterRatio);
if (mKeyLabelRatio >= 0.0f)
mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio);
+ mKeyLargeLabelSize = (int)(keyHeight * mKeyLargeLabelRatio);
mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio);
mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio);
mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio);
@@ -385,11 +389,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
* @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();
@@ -570,7 +569,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// For characters, use large font. For labels like "Done", use smaller font.
paint.setTypeface(key.selectTypeface(params.mKeyTextStyle));
final int labelSize = key.selectTextSize(params.mKeyLetterSize,
- params.mKeyLargeLetterSize, params.mKeyLabelSize, params.mKeyHintLabelSize);
+ params.mKeyLargeLetterSize, params.mKeyLabelSize, params.mKeyLargeLabelSize,
+ params.mKeyHintLabelSize);
paint.setTextSize(labelSize);
final float labelCharHeight = getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint);
final float labelCharWidth = getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 2d80a798d..c85122ad3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -20,6 +20,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.ResearchLogger;
import com.android.inputmethod.latin.define.ProductionFlag;
@@ -29,9 +30,9 @@ import com.android.inputmethod.latin.define.ProductionFlag;
* 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 #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)},
- * {@link #onUpdateShiftState(boolean)}, {@link #onLongPressTimeout(int)}.
+ * {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
+ * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
+ * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
*
* The actions are {@link SwitchActions}'s methods.
*/
@@ -50,7 +51,7 @@ public class KeyboardState {
public void setSymbolsShiftedKeyboard();
/**
- * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}.
+ * Request to call back {@link KeyboardState#onUpdateShiftState(int)}.
*/
public void requestUpdatingShiftState();
@@ -296,9 +297,10 @@ public class KeyboardState {
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);
@@ -312,6 +314,21 @@ public class KeyboardState {
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();
+ }
+ }
}
}
@@ -371,14 +388,14 @@ public class KeyboardState {
}
}
- public void onUpdateShiftState(boolean autoCaps) {
+ public void onUpdateShiftState(int autoCaps) {
if (DEBUG_EVENT) {
Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
}
updateAlphabetShiftState(autoCaps);
}
- private void updateAlphabetShiftState(boolean autoCaps) {
+ private void updateAlphabetShiftState(int autoCaps) {
if (!mIsAlphabetMode) return;
if (!mShiftKeyState.isReleasing()) {
// Ignore update shift state event while the shift key is being pressed (including
@@ -386,7 +403,7 @@ public class KeyboardState {
return;
}
if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
- if (mShiftKeyState.isReleasing() && autoCaps) {
+ if (mShiftKeyState.isReleasing() && autoCaps != Constants.TextUtils.CAP_MODE_OFF) {
// Only when shift key is releasing, automatic temporary upper case will be set.
setShifted(AUTOMATIC_SHIFT);
} else {
@@ -521,7 +538,7 @@ public class KeyboardState {
return false;
}
- public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) {
+ public void onCodeInput(int code, boolean isSinglePointer, int autoCaps) {
if (DEBUG_EVENT) {
Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code)
+ " single=" + isSinglePointer
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 7c2284569..e79db367c 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -106,6 +106,21 @@ public final class Constants {
}
}
+ public static class TextUtils {
+ /**
+ * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
+ * characters. This value may be used with
+ * {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
+ * {@link android.text.TextUtils#CAP_MODE_WORDS}, and
+ * {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
+ */
+ public static final int CAP_MODE_OFF = 0;
+
+ private TextUtils() {
+ // This utility class is not publicly instantiable.
+ }
+ }
+
private Constants() {
// This utility class is not publicly instantiable.
}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 22787c218..4b77473d9 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -60,7 +60,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
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 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
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.
@@ -175,7 +171,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
// 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 83bc9046b..2f3395245 100644
--- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java
@@ -28,6 +28,12 @@ import android.util.Log;
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 22d8f24f1..08f585485 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.keyboard.ProximityInfo;
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 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
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 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
*/
// 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 261755f53..b474a8558 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -106,6 +106,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
/** 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 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
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);
@@ -1032,26 +1041,32 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
updateSuggestions();
}
- public boolean getCurrentAutoCapsState() {
- if (!mSettingsValues.mAutoCap) return false;
+ public int getCurrentAutoCapsState() {
+ if (!mSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
final EditorInfo ei = getCurrentInputEditorInfo();
- if (ei == null) return false;
+ if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
final int inputType = ei.inputType;
- if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) return true;
+ if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
+ return TextUtils.CAP_MODE_CHARACTERS;
+ }
final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
| InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
- if (noNeedToCheckCapsMode) return false;
+ 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 false;
+ if (ic == null) return Constants.TextUtils.CAP_MODE_OFF;
// TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
// Note: getCursorCapsMode() returns the current capitalization mode that is any
// combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none
// of them.
- return ic.getCursorCapsMode(inputType) != 0;
+ return ic.getCursorCapsMode(inputType);
}
// "ic" may be null
@@ -1121,7 +1136,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@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();
@@ -1139,7 +1158,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// 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) {
@@ -1152,9 +1170,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return true;
}
return false;
- case CODE_HAPTIC_AND_AUDIO_FEEDBACK:
- hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED);
- return true;
}
return false;
}
@@ -1522,7 +1537,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ic != null) {
// If it's the first letter, make note of auto-caps state
if (mWordComposer.size() == 1) {
- mWordComposer.setAutoCapitalized(getCurrentAutoCapsState());
+ mWordComposer.setAutoCapitalized(
+ getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF);
}
ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
}
@@ -1834,10 +1850,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void pickSuggestionManually(final int index, final CharSequence suggestion,
int x, int y) {
- final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
final InputConnection ic = getCurrentInputConnection();
- if (ic != null) ic.beginBatchEdit();
+ if (null != ic) ic.beginBatchEdit();
+ pickSuggestionManuallyWhileInBatchEdit(index, suggestion, x, y, ic);
+ if (null != ic) ic.endBatchEdit();
+ }
+ public void pickSuggestionManuallyWhileInBatchEdit(final int index,
+ final CharSequence suggestion, final int x, final int y, final InputConnection ic) {
+ final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
if (suggestion.length() == 1 && isShowingPunctuationList()) {
// Word separators are suggested before the user inputs something.
@@ -1933,7 +1954,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestions();
}
}
- if (null != ic) ic.endBatchEdit();
}
/**
@@ -2245,6 +2265,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
+ // 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/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 566af7061..aa979a66f 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -444,7 +444,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
public static void keyboardState_onCodeInput(
- final int code, final boolean isSinglePointer, final boolean autoCaps,
+ final int code, final boolean isSinglePointer, final int autoCaps,
final KeyboardState keyboardState) {
if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) {
final String s = "onCodeInput: code=" + Keyboard.printableCode(code)
diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
index 188259ff8..4994e5902 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedContactsBinaryDictionary.java
@@ -26,7 +26,6 @@ public class SynchronouslyLoadedContactsBinaryDictionary extends ContactsBinaryD
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 000000000..1606a34e0
--- /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 b78be89b8..23a49c192 100644
--- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserDictionary.java
@@ -21,6 +21,7 @@ import android.content.Context;
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 @@ public class SynchronouslyLoadedUserDictionary extends UserDictionary {
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 000000000..6fa1a25a1
--- /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 218bac72a..81e2fdce4 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -29,6 +29,12 @@ import com.android.inputmethod.keyboard.ProximityInfo;
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/UserHistoryForgettingCurveUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
new file mode 100644
index 000000000..eb3881726
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/UserHistoryForgettingCurveUtils.java
@@ -0,0 +1,120 @@
+/*
+ * 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;
+
+public class UserHistoryForgettingCurveUtils {
+ private static final int FC_FREQ_MAX = 127;
+ /* package */ static final int COUNT_MAX = 3;
+ private static final int FC_LEVEL_MAX = 3;
+ /* package */ static final int ELAPSED_TIME_MAX = 15;
+ private static final int ELAPSED_TIME_INTERVAL_HOURS = 6;
+ private static final int HALF_LIFE_HOURS = 48;
+
+ /* package */ static int fcToElapsedTime(byte fc) {
+ return fc & 0x0F;
+ }
+
+ /* package */ static int fcToCount(byte fc) {
+ return (fc >> 4) & 0x03;
+ }
+
+ /* package */ static int fcToLevel(byte fc) {
+ return (fc >> 6) & 0x03;
+ }
+
+ private static int calcFreq(int elapsedTime, int count, int level) {
+ if (level <= 0) {
+ // Reserved words, just return 0
+ return 0;
+ }
+ if (count == COUNT_MAX) {
+ // Temporary promote because it's frequently typed recently
+ ++level;
+ }
+ final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
+ final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
+ return MathUtils.SCORE_TABLE[l - 1][et];
+ }
+
+ /* pakcage */ static byte calcFc(int elapsedTime, int count, int level) {
+ final int et = Math.min(FC_FREQ_MAX, Math.max(0, elapsedTime));
+ final int c = Math.min(COUNT_MAX, Math.max(0, count));
+ final int l = Math.min(FC_LEVEL_MAX, Math.max(0, level));
+ return (byte)(et | (c << 4) | (l << 6));
+ }
+
+ public static int fcToFreq(byte fc) {
+ final int elapsedTime = fcToElapsedTime(fc);
+ final int count = fcToCount(fc);
+ final int level = fcToLevel(fc);
+ return calcFreq(elapsedTime, count, level);
+ }
+
+ public static byte pushElapsedTime(byte fc) {
+ int elapsedTime = fcToElapsedTime(fc);
+ int count = fcToCount(fc);
+ int level = fcToLevel(fc);
+ if (elapsedTime >= ELAPSED_TIME_MAX) {
+ // Downgrade level
+ elapsedTime = 0;
+ count = COUNT_MAX;
+ --level;
+ } else {
+ ++elapsedTime;
+ }
+ return calcFc(elapsedTime, count, level);
+ }
+
+ public static byte pushCount(byte fc, boolean isValid) {
+ final int elapsedTime = fcToElapsedTime(fc);
+ int count = fcToCount(fc);
+ int level = fcToLevel(fc);
+ if ((elapsedTime == 0 && count >= COUNT_MAX) || (isValid && level == 0)) {
+ // Upgrade level
+ ++level;
+ count = 0;
+ } else {
+ ++count;
+ }
+ return calcFc(0, count, level);
+ }
+
+ private static class MathUtils {
+ public static final int[][] SCORE_TABLE = new int[FC_LEVEL_MAX][ELAPSED_TIME_MAX + 1];
+ static {
+ for (int i = 0; i < FC_LEVEL_MAX; ++i) {
+ final double initialFreq;
+ if (i >= 2) {
+ initialFreq = (double)FC_FREQ_MAX;
+ } else if (i == 1) {
+ initialFreq = (double)FC_FREQ_MAX / 2;
+ } else if (i == 0) {
+ initialFreq = (double)FC_FREQ_MAX / 4;
+ } else {
+ continue;
+ }
+ for (int j = 0; j < ELAPSED_TIME_MAX; ++j) {
+ final double elapsedHour = j * ELAPSED_TIME_INTERVAL_HOURS;
+ final double freq =
+ initialFreq * Math.pow(initialFreq, elapsedHour / HALF_LIFE_HOURS);
+ final int intFreq = Math.min(FC_FREQ_MAX, Math.max(0, (int)freq));
+ SCORE_TABLE[i][j] = intFreq;
+ }
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index d7c8e3850..9807d2892 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.R;
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 @@ public class AndroidSpellCheckerService extends SpellCheckerService
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 26a9415c4..3d593aaa7 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 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
}
/**
- * 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
*/