diff options
558 files changed, 33447 insertions, 19346 deletions
diff --git a/Android.mk b/Android.mk index 8f1acc55a..91b2fbbb0 100644 --- a/Android.mk +++ b/Android.mk @@ -12,6 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -LOCAL_PATH := $(call my-dir) - -include $(call all-makefiles-under,$(LOCAL_PATH)) +include $(call all-subdir-makefiles) diff --git a/dictionaries/sample.xml b/dictionaries/sample.xml index 85233b63a..ad98f2b6f 100644 --- a/dictionaries/sample.xml +++ b/dictionaries/sample.xml @@ -2,7 +2,9 @@ for use by the Latin IME. The format of the word list is a flat list of word entries. Each entry has a frequency between 255 and 0. - Highest frequency words get more weight in the prediction algorithm. + Highest frequency words get more weight in the prediction algorithm. As a + special case, a weight of 0 is taken to mean profanity - words that should + not be considered a typo, but that should never be suggested explicitly. You can capitalize words that must always be capitalized, such as "January". You can have a capitalized and a non-capitalized word as separate entries, such as "robin" and "Robin". @@ -13,4 +15,3 @@ <w f="128">sample</w> <w f="1">wordlist</w> </wordlist> - diff --git a/java/Android.mk b/java/Android.mk index e9fa52ef3..52cc18b26 100644 --- a/java/Android.mk +++ b/java/Android.mk @@ -1,3 +1,17 @@ +# Copyright (C) 2011 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. + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -9,11 +23,14 @@ LOCAL_PACKAGE_NAME := LatinIME LOCAL_CERTIFICATE := shared +# We want to package libjni_latinime.so into the apk. LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime +# We want to install libjni_latinime.so to the system partition if LatinIME gets installed. LOCAL_REQUIRED_MODULES := libjni_latinime LOCAL_STATIC_JAVA_LIBRARIES := android-common LOCAL_STATIC_JAVA_LIBRARIES += inputmethod-common +LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4 # Do not compress dictionary files to mmap dict data runtime LOCAL_AAPT_FLAGS := -0 .dict diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml index b0525326c..e663c90f2 100644 --- a/java/AndroidManifest.xml +++ b/java/AndroidManifest.xml @@ -5,16 +5,15 @@ <uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_USER_DICTIONARY" /> - <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> - <application android:label="@string/english_ime_name" + <application android:label="@string/aosp_android_keyboard_ime_name" android:icon="@drawable/ic_ime_settings" android:backupAgent="BackupAgent" android:killAfterRestore="false"> <service android:name="LatinIME" - android:label="@string/english_ime_name" + android:label="@string/aosp_android_keyboard_ime_name" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> diff --git a/java/proguard.flags b/java/proguard.flags index 33af890ec..a5a667987 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -35,6 +35,12 @@ *; } --keep class com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder$MiniKeyboardParams { +-keep class com.android.inputmethod.keyboard.MoreKeysKeyboard$Builder$MoreKeysKeyboardParams { <init>(...); } + +# The support library contains references to newer platform versions. +# Don't warn about those in case this app is linking against an older +# platform version. We know about them, and they are safe. +-dontwarn android.support.v4.** +-dontwarn android.support.v13.** diff --git a/java/res/anim/alt_code_key_while_typing_fadein.xml b/java/res/anim/alt_code_key_while_typing_fadein.xml new file mode 100644 index 000000000..3f5fd5d48 --- /dev/null +++ b/java/res/anim/alt_code_key_while_typing_fadein.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<animator + xmlns:android="http://schemas.android.com/apk/res/android" + android:valueType="intType" + android:duration="100" + android:valueFrom="128" + android:valueTo="255" /> diff --git a/java/res/anim/alt_code_key_while_typing_fadeout.xml b/java/res/anim/alt_code_key_while_typing_fadeout.xml new file mode 100644 index 000000000..ed4a6f298 --- /dev/null +++ b/java/res/anim/alt_code_key_while_typing_fadeout.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<animator + xmlns:android="http://schemas.android.com/apk/res/android" + android:valueType="intType" + android:duration="70" + android:valueFrom="255" + android:valueTo="128" /> diff --git a/java/res/anim/language_on_spacebar_fadeout.xml b/java/res/anim/language_on_spacebar_fadeout.xml new file mode 100644 index 000000000..f66e1627b --- /dev/null +++ b/java/res/anim/language_on_spacebar_fadeout.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<animator + xmlns:android="http://schemas.android.com/apk/res/android" + android:valueType="intType" + android:startOffset="1200" + android:duration="200" + android:valueFrom="255" + android:valueTo="128" /> diff --git a/java/res/anim/mini_keyboard_fadein.xml b/java/res/anim/more_keys_keyboard_fadein.xml index f80e8b8de..c781f36ad 100644 --- a/java/res/anim/mini_keyboard_fadein.xml +++ b/java/res/anim/more_keys_keyboard_fadein.xml @@ -25,5 +25,5 @@ <alpha android:fromAlpha="0.5" android:toAlpha="1.0" - android:duration="@integer/config_mini_keyboard_fadein_anim_time" /> + android:duration="@integer/config_more_keys_keyboard_fadein_anim_time" /> </set> diff --git a/java/res/anim/mini_keyboard_fadeout.xml b/java/res/anim/more_keys_keyboard_fadeout.xml index 535b100ae..32fae6bd8 100644 --- a/java/res/anim/mini_keyboard_fadeout.xml +++ b/java/res/anim/more_keys_keyboard_fadeout.xml @@ -25,5 +25,5 @@ <alpha android:fromAlpha="1.0" android:toAlpha="0.0" - android:duration="@integer/config_mini_keyboard_fadeout_anim_time" /> + android:duration="@integer/config_more_keys_keyboard_fadeout_anim_time" /> </set> diff --git a/java/res/drawable-hdpi/more_keys_divider.png b/java/res/drawable-hdpi/more_keys_divider.png Binary files differnew file mode 100644 index 000000000..a5912f95c --- /dev/null +++ b/java/res/drawable-hdpi/more_keys_divider.png diff --git a/java/res/drawable-hdpi/sym_keyboard_language_switch.png b/java/res/drawable-hdpi/sym_keyboard_language_switch.png Binary files differnew file mode 100644 index 000000000..fa747642d --- /dev/null +++ b/java/res/drawable-hdpi/sym_keyboard_language_switch.png diff --git a/java/res/drawable-mdpi/more_keys_divider.png b/java/res/drawable-mdpi/more_keys_divider.png Binary files differnew file mode 100644 index 000000000..a46284f21 --- /dev/null +++ b/java/res/drawable-mdpi/more_keys_divider.png diff --git a/java/res/drawable-mdpi/sym_keyboard_language_switch.png b/java/res/drawable-mdpi/sym_keyboard_language_switch.png Binary files differnew file mode 100644 index 000000000..f30c1b640 --- /dev/null +++ b/java/res/drawable-mdpi/sym_keyboard_language_switch.png diff --git a/java/res/drawable-xhdpi/more_keys_divider.png b/java/res/drawable-xhdpi/more_keys_divider.png Binary files differnew file mode 100644 index 000000000..178594bf0 --- /dev/null +++ b/java/res/drawable-xhdpi/more_keys_divider.png diff --git a/java/res/drawable/background_voice.xml b/java/res/drawable/background_voice.xml index 3b6137df3..49a419110 100644 --- a/java/res/drawable/background_voice.xml +++ b/java/res/drawable/background_voice.xml @@ -22,4 +22,4 @@ android:startColor="#ff000000" android:endColor="#ff000e29" android:angle="90" /> -</shape>
\ No newline at end of file +</shape> diff --git a/java/res/drawable/btn_center.xml b/java/res/drawable/btn_center.xml index 9998b56e2..3ac21297c 100644 --- a/java/res/drawable/btn_center.xml +++ b/java/res/drawable/btn_center.xml @@ -37,4 +37,4 @@ android:drawable="@drawable/btn_center_default" /> <item android:drawable="@drawable/btn_center_default" /> -</selector>
\ No newline at end of file +</selector> diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index 2e0cddc28..0a8d71f30 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -20,15 +20,15 @@ <com.android.inputmethod.latin.InputView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" > + <!-- The height of key_preview_backing view will automatically be determined by code. --> <View android:id="@+id/key_preview_backing" android:layout_width="match_parent" - android:layout_height="@dimen/key_preview_backing_height" /> + android:layout_height="0dip" /> <!-- On tablets, the suggestions strip is centered with horizontal paddings on both sides because width of the landscape mode is too long for the suggestions strip. This @@ -43,7 +43,7 @@ android:layout_width="@dimen/suggestions_strip_padding" android:layout_height="@dimen/suggestions_strip_height" style="?attr/suggestionsStripBackgroundStyle" /> - <com.android.inputmethod.latin.SuggestionsView + <com.android.inputmethod.latin.suggestions.SuggestionsView android:id="@+id/suggestions_view" android:layout_weight="1.0" android:layout_width="0dp" diff --git a/java/res/layout/mini_keyboard.xml b/java/res/layout/more_keys_keyboard.xml index f7cd75cf3..6b2464b99 100644 --- a/java/res/layout/mini_keyboard.xml +++ b/java/res/layout/more_keys_keyboard.xml @@ -22,11 +22,11 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" - style="?attr/miniKeyboardPanelStyle" + style="?attr/moreKeysKeyboardPanelStyle" > - <com.android.inputmethod.keyboard.MiniKeyboardView + <com.android.inputmethod.keyboard.MoreKeysKeyboardView xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - android:id="@+id/mini_keyboard_view" + android:id="@+id/more_keys_keyboard_view" android:layout_width="wrap_content" android:layout_height="wrap_content" /> diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml index c49f95878..49a00c6b5 100644 --- a/java/res/layout/more_suggestions.xml +++ b/java/res/layout/more_suggestions.xml @@ -22,9 +22,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" - style="?attr/miniKeyboardPanelStyle" + style="?attr/moreKeysKeyboardPanelStyle" > - <com.android.inputmethod.latin.MoreSuggestionsView + <com.android.inputmethod.latin.suggestions.MoreSuggestionsView xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" android:id="@+id/more_suggestions_view" android:layout_width="wrap_content" diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index 36c9d4bc4..b1f7658d3 100644 --- a/java/res/values-af/strings.xml +++ b/java/res/values-af/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-sleutelbord"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-sleutelbord (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android-sleutelbordinstellings"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropsies"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korrigering"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-speltoetser"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-speltoetser (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Speltoetser se instellings"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Gebruik nabyheidsdata"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gebruik \'n sleutelbordagtige nabyheidsalgoritme vir die speltoetser"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Soek kontakname op"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Speltoetser gebruik inskrywings uit jou kontaklys"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Klank met sleuteldruk"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Opspring met sleuteldruk"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"Tekskorrigering"</string> <string name="misc_category" msgid="6894192814868233453">"Ander opsies"</string> <string name="advanced_settings" msgid="362895144495591463">"Gevorderde instellings"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opsies vir gevorderde gebruikers"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opsies vir kundiges"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skakel oor na die ander invoermetodes"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Taal-skakelsleutel dek ook ander invoermetodes"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Onderdruk taalwissel-sleutel"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Sleutelopspringer-wagperiode"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen wagperiode nie"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Wys altyd"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Wys in portretmodus"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Versteek altyd"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Wys instellingsleutel"</string> <string name="auto_correction" msgid="4979925752001319458">"Outokorrigering"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Spasiebalk en leestekens korrigeer outomaties woorde wat verkeerd gespel is"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Af"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Gestoor"</string> <string name="label_go_key" msgid="1635148082137219148">"Gaan"</string> <string name="label_next_key" msgid="362972844525672568">"Volgende"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Vorige"</string> <string name="label_done_key" msgid="2441578748772529288">"Klaar"</string> <string name="label_send_key" msgid="2815056534433717444">"Stuur"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Geen teks ingevoer nie"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Sleutelkode %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift geaktiveer"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bokas-slot geaktiveer"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om te deaktiveer)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kasslot aan (tik om te deaktiveer)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Vee uit"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbole"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Steminvoering"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Glimlag-gesiggie"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Tydperk"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Links-hakie"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Regs-hakie"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dubbelpunt"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Kommapunt"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uitroepteken"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vraagteken"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbel-aanhalingsteken"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkel-aanhalingsteken"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Vierkantswortel"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Handelsmerk"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Per adres"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Ster"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pond"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellips"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Onderste dubbel-aanhalingsteken"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift geaktiveer"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kasslot geaktiveer"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift gedeaktiveer"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simboolmodus"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Lettermodus"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Foonmodus"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Foonsimbool-modus"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Steminvoering"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Steminvoering vir jou taal word nie tans ondersteun nie, maar werk wel in Engels."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Steminvoer gebruik Google se spraakherkenning. "<a href="http://m.google.com/privacy">"Die Mobiel-privaatheidsbeleid"</a>" is van toepassing."</string> @@ -144,10 +137,9 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiveer gebruikerterugvoer"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Help hierdie invoermetode-redigeerder te verbeter deur gebruikstatistiek en omvalverslae outomaties na Google te stuur."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Sleutelbordtema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Duitse QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engels (VK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Bruikbaarheidstudie-modus"</string> - <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Vibrasie-tydsduur met sleuteldruk"</string> - <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Volume met sleuteldruk"</string> + <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Sleuteldruk se vibrasie-tydsduurinstellings"</string> + <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Sleuteldruk se klankvolume-instellings"</string> </resources> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index d5280bc64..bb0c493b2 100644 --- a/java/res/values-am/strings.xml +++ b/java/res/values-am/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"የAndroid ቁልፍሰሌዳ"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"የAndroid ቁልፍ ሰሌዳ (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"የAndroid ቁልፍሰሌዳ ቅንብሮች"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"ግቤት አማራጮች"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"የAndroid ማስተካከያ"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android የፊደል ማረሚያ"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android የፊደል ማረሚያ (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"የፊደል አራሚ ቅንብሮች"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"የቀረቤታ ውሂብ ተጠቀም"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"ለፊደል አራሚ የሰሌዳ ቁልፍ አይነት የቀረበ ስልተ ቀመር ተጠቀም"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"የእውቅያ ስሞችን ተመልከት"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"ፊደል አራሚ ከእውቅያ ዝርዝርህ የገቡትን ይጠቀማል"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"በቁልፍመጫንጊዜ አንዝር"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"በቁልፍ መጫን ላይ የሚወጣ ድምፅ"</string> <string name="popup_on_keypress" msgid="123894815723512944">"ቁልፍ ጫን ላይ ብቅ ባይ"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"ፅሁፍ አስተካክል"</string> <string name="misc_category" msgid="6894192814868233453">"ሌሎች አማራጮች"</string> <string name="advanced_settings" msgid="362895144495591463">"የላቁ ቅንብሮች"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"ለብቁ ተጠቃሚዎች አማራጮች"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"ለብቁ ተጠቃሚዎች አማራጮች"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"ወደ ሌሎች የግቤት ስልቶች ቀይር"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"የቋንቋ መቀየሪያ ቁልፍ ሌሎች የግቤት ስልቶችንም ይሸፍናል"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"የቋንቋ መቀየሪያ ቁልፍ አፍን"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"የቁልፍ ብቅ ባይ መዘግየትን ያስወገዳል"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"የዘገየ የለም"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ነባሪ"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"ሁልጊዜ አሳይ"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"በቁመት ሁነታ አሳይ"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"ሁልጊዜ ደብቅ"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"የቅንብሮች ቁልፍ አሳይ"</string> <string name="auto_correction" msgid="4979925752001319458">"በራስ ማስተካከል"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"የቦታ ቁልፍ እና ሥርዓተ ነጥብ በስህተት የተተየቡ ቃላትን በራስሰር ያስተካክላሉ ።"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"ውጪ"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ተቀምጧል"</string> <string name="label_go_key" msgid="1635148082137219148">"ሂድ"</string> <string name="label_next_key" msgid="362972844525672568">"በመቀጠል"</string> + <string name="label_previous_key" msgid="1211868118071386787">"ቀዳሚ"</string> <string name="label_done_key" msgid="2441578748772529288">"ተከናውኗል"</string> <string name="label_send_key" msgid="2815056534433717444">" ይላኩ"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"ምንም ፅሁፍ አልገባም"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"የቁልፍ ኮድ%d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"ቀይር"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"መቀያየሪያ ቁልፍ ነቅቷል"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"አቢያት ማርጊያነቅቷል"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"ቅያር በርቷል (ለማሰናክል ንካ)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"አቢያት ማድረጊያ ቁልጥ በርቷል (ለማሰናክል ንካ)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"ሰርዝ"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"ምልክቶች"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"ደብዳቤዎች"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"የድምፅ ግቤ ት"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"የፈገግታ ፊት"</string> <string name="spoken_description_return" msgid="8178083177238315647">"ተመለስ"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"ነጠላ ሰረዝ"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"ክፍለ ጊዜ"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"የግራ ቅንፍ"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"የቀኝ ቅንፍ"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"ሁለት ነጥብ"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"ድርብ ሰረዝ"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"ቃል አጋኖ"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"ጥያቄ ምልክት"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"ድርብ ጥቅስ"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"ነጠላ ትምህርተ ጥቅስ"</string> <string name="spoken_description_dot" msgid="40711082435231673">"ነጥብ"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"ስክዌር ሩት"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"ዴልታ"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"የንግድምልክት"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"መጠንቀቅ"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"ኮከብ"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"ፓውንድ"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"ዝቅ ያለ ድርብ ትምህርተ ጥቅስ"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"ቅያር ቁልፍ ነቅቷል"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"አቢያት ማድረጊያ ነቅቷል"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"ቅያር ተሰናክሏል"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"የምልክቶች ሁኔታ ላይ"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"የደብዳቤዎች ሁኔታ ላይ"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"የስልክ ሁኔታ ላይ"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"የስልክ ምልክቶች ሁኔታ ላይ"</string> <string name="voice_warning_title" msgid="4419354150908395008">"የድምፅ ግቤ ት"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"የድምፅ ግቤት በአሁኑ ጊዜ ለእርስዎን ቋንቋ አይደግፍም፣ ግን በእንግሊዘኛ ይሰራል።"</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"የድምፅ ግቤት የGoogleን ንግግር ለይቶ ማወቂያ ይጠቀማል።"<a href="http://m.google.com/privacy">"የተንቀሳቃሽ ስልክ ግላዊ ፖሊሲ"</a>" ይተገበራል።"</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"የተጠቃሚ ግብረ ምላሽ አንቃ"</string> <string name="prefs_description_log" msgid="5827825607258246003">"ወደ Google የተሰናከለ ሪፖርቶች እና አጠቃቀም ስታስቲክስ በራስ ሰር በመላክ ይህን ግቤት ሜተድ አርትኢ እገዛ ያሻሽላል።"</string> <string name="keyboard_layout" msgid="8451164783510487501">"የቁልፍ ሰሌዳ ገጽታ"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"የጀመርን QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"እንግሊዘኛ (የታላቋ ብሪታንያ)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"እንግሊዘኛ (ዩ.ኤስ)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"የተገልጋይነት ጥናት ሁነታ"</string> diff --git a/java/res/values-ar/donottranslate-more-keys.xml b/java/res/values-ar/donottranslate-more-keys.xml index cde686084..ecad0bb0d 100644 --- a/java/res/values-ar/donottranslate-more-keys.xml +++ b/java/res/values-ar/donottranslate-more-keys.xml @@ -18,94 +18,143 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- \u060c: ARABIC COMMA - \u061b: ARABIC SEMICOLON - \u061f: ARABIC QUESTION MARK --> - <!-- \u0650: ARABIC KASRA - \u064e: ARABIC FATHA - \u064b: ARABIC FATHATAN - \u0640: ARABIC TATWEEL - \u064d: ARABIC KASRATAN - \u0670: ARABIC LETTER SUPERSCRIPT ALEF - \u0656: ARABIC SUBSCRIPT ALEF - \u0654: ARABIC HAMZA ABOVE - \u0655: ARABIC HAMZA BELOW --> - <!-- \u0651: ARABIC SHADDA - \u0652: ARABIC SUKUN - \u064c: ARABIC DAMMATAN - \u0653: ARABIC MADDAH ABOVE - \u064f: ARABIC DAMMA --> + <!-- U+061F: "؟" ARABIC QUESTION MARK + U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064D: "ٍ" ARABIC KASRATAN + U+064B: "ً" ARABIC FATHATAN + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0655: "ٕ" ARABIC HAMZA BELOW + U+0654: "ٔ" ARABIC HAMZA ABOVE --> + <!-- U+064F: "ُ" ARABIC DAMMA + U+064C: "ٌ" ARABIC DAMMATAN + U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+0640: "ـ" ARABIC TATWEEL --> <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> - <!-- TODO: Will introduce "grouping marks" to the more characters specification. --> - <string name="more_keys_for_punctuation">"\u060c,\u061b,\u061f,!,:,-,/,\',\",\u0640\u0640\u0640|\u0640,\u064e,\u0650,\u064b,\u064d,\u0670,\u0656,\u0655,\u0654,\u0653,\u0652,\u0651,\u064c,\u064f"</string> - <integer name="mini_keyboard_column_for_punctuation">9</integer> - <string name="keyhintlabel_for_punctuation">\u064b</string> - <string name="keylabel_for_symbols_1">"١"</string> - <string name="keylabel_for_symbols_2">"٢"</string> - <string name="keylabel_for_symbols_3">"٣"</string> - <string name="keylabel_for_symbols_4">"٤"</string> - <string name="keylabel_for_symbols_5">"٥"</string> - <string name="keylabel_for_symbols_6">"٦"</string> - <string name="keylabel_for_symbols_7">"٧"</string> - <string name="keylabel_for_symbols_8">"٨"</string> - <string name="keylabel_for_symbols_9">"٩"</string> - <string name="keylabel_for_symbols_0">"٠"</string> - <string name="more_keys_for_symbols_1">1</string> - <string name="more_keys_for_symbols_2">2</string> - <string name="more_keys_for_symbols_3">3</string> - <string name="more_keys_for_symbols_4">4</string> - <string name="more_keys_for_symbols_5">5</string> - <string name="more_keys_for_symbols_6">6</string> - <string name="more_keys_for_symbols_7">7</string> - <string name="more_keys_for_symbols_8">8</string> - <string name="more_keys_for_symbols_9">9</string> - <!-- \u066b: ARABIC DECIMAL SEPARATOR - \u066c: ARABIC THOUSANDS SEPARATOR --> - <string name="more_keys_for_symbols_0">0,\u066b,\u066c</string> - <string name="keylabel_for_comma">\u060c</string> - <string name="keylabel_for_f1">\u060c</string> - <string name="keylabel_for_symbols_question">\u061f</string> - <string name="keylabel_for_symbols_semicolon">\u061b</string> - <!-- \u066a: ARABIC PERCENT SIGN --> - <string name="keylabel_for_symbols_percent">\u066a</string> - <string name="more_keys_for_comma">,</string> - <string name="more_keys_for_f1">,</string> - <!-- @icon/3 is iconSettingsKey --> - <string name="more_keys_for_f1_settings">\\,,\@icon/3|\@integer/key_settings</string> - <!-- @icon/7 is iconTabKey --> - <string name="more_keys_for_f1_navigate">\\,,\@icon/7|\@integer/key_tab</string> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',-,:,!,؟,،,؛,ِ,َ,ٍ,ً,ٖ,ٰ,ٕ,ٔ,ُ,ٌ,ّ,ْ,ٓ,ـــ|ـ,/"</string> + <string name="keyhintlabel_for_punctuation">ً</string> + <!-- U+0661: "١" ARABIC-INDIC DIGIT ONE --> + <string name="keylabel_for_symbols_1">١</string> + <!-- U+0662: "٢" ARABIC-INDIC DIGIT TWO --> + <string name="keylabel_for_symbols_2">٢</string> + <!-- U+0663: "٣" ARABIC-INDIC DIGIT THREE --> + <string name="keylabel_for_symbols_3">٣</string> + <!-- U+0664: "٤" ARABIC-INDIC DIGIT FOUR --> + <string name="keylabel_for_symbols_4">٤</string> + <!-- U+0665: "٥" ARABIC-INDIC DIGIT FIVE --> + <string name="keylabel_for_symbols_5">٥</string> + <!-- U+0666: "٦" ARABIC-INDIC DIGIT SIX --> + <string name="keylabel_for_symbols_6">٦</string> + <!-- U+0667: "٧" ARABIC-INDIC DIGIT SEVEN --> + <string name="keylabel_for_symbols_7">٧</string> + <!-- U+0668: "٨" ARABIC-INDIC DIGIT EIGHT --> + <string name="keylabel_for_symbols_8">٨</string> + <!-- U+0669: "٩" ARABIC-INDIC DIGIT NINE --> + <string name="keylabel_for_symbols_9">٩</string> + <!-- U+0660: "٠" ARABIC-INDIC DIGIT ZERO --> + <string name="keylabel_for_symbols_0">٠</string> + <string name="additional_more_keys_for_symbols_1">1</string> + <string name="additional_more_keys_for_symbols_2">2</string> + <string name="additional_more_keys_for_symbols_3">3</string> + <string name="additional_more_keys_for_symbols_4">4</string> + <string name="additional_more_keys_for_symbols_5">5</string> + <string name="additional_more_keys_for_symbols_6">6</string> + <string name="additional_more_keys_for_symbols_7">7</string> + <string name="additional_more_keys_for_symbols_8">8</string> + <string name="additional_more_keys_for_symbols_9">9</string> + <!-- U+066B: "٫" ARABIC DECIMAL SEPARATOR + U+066C: "٬" ARABIC THOUSANDS SEPARATOR --> + <string name="additional_more_keys_for_symbols_0">0,٫,٬</string> + <!-- U+060C: "،" ARABIC COMMA --> + <string name="keylabel_for_comma">،</string> + <string name="more_keys_for_comma">"\\,"</string> + <string name="keylabel_for_symbols_question">؟</string> + <string name="keylabel_for_symbols_semicolon">؛</string> + <!-- U+066A: "٪" ARABIC PERCENT SIGN --> + <string name="keylabel_for_symbols_percent">٪</string> <string name="more_keys_for_symbols_question">\?</string> <string name="more_keys_for_symbols_semicolon">;</string> - <string name="more_keys_for_symbols_percent">%,‰</string> - <!-- \u060c: ARABIC COMMA - \u061b: ARABIC SEMICOLON - \u061f: ARABIC QUESTION MARK --> - <string name="keylabel_for_apostrophe">"\u060c"</string> + <!-- U+2030: "‰" PER MILLE SIGN --> + <string name="more_keys_for_symbols_percent">%,‰</string> + <!-- U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON + U+061F: "؟" ARABIC QUESTION MARK --> + <string name="keylabel_for_apostrophe">،</string> <string name="keylabel_for_dash">"."</string> - <string name="keyhintlabel_for_apostrophe">"\u061f"</string> - <string name="keyhintlabel_for_dash">"\u064b"</string> - <string name="more_keys_for_apostrophe">"\u061f,\u061b,!,:,-,/,\',\""</string> - <!-- \u0651: ARABIC SHADDA - \u0652: ARABIC SUKUN - \u064c: ARABIC DAMMATAN - \u0653: ARABIC MADDAH ABOVE - \u064f: ARABIC DAMMA --> - <!-- \u0650: ARABIC KASRA - \u064e: ARABIC FATHA - \u064b: ARABIC FATHATAN - \u0640: ARABIC TATWEEL - \u064d: ARABIC KASRATAN --> - <!-- \u0670: ARABIC LETTER SUPERSCRIPT ALEF - \u0656: ARABIC SUBSCRIPT ALEF - \u0654: ARABIC HAMZA ABOVE - \u0655: ARABIC HAMZA BELOW --> + <string name="keyhintlabel_for_apostrophe">؟</string> + <string name="keyhintlabel_for_dash">ً</string> + <string name="more_keys_for_apostrophe">"؟,؛,!,:,-,/,\',\""</string> + <!-- U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+064C: "ٌ" ARABIC DAMMATAN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+064F: "ُ" ARABIC DAMMA --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064B: "ً" ARABIC FATHATAN + U+0640: "ـ" ARABIC TATWEEL + U+064D: "ٍ" ARABIC KASRATAN --> + <!-- U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0654: "ٔ" ARABIC HAMZA ABOVE + U+0655: "ٕ" ARABIC HAMZA BELOW --> <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> - <string name="more_keys_for_dash">"\u0651,\u0652,\u064c,\u0653,\u064f,\u0650,\u064e,\u064b,\u0640\u0640\u0640|\u0640,\u064d,\u0654,\u0656,\u0655,\u0670"</string> - <string name="more_keys_for_bullet">♪</string> - <!-- \u066d: ARABIC FIVE POINTED STAR --> - <string name="more_keys_for_star">★,\u066d</string> - <!-- \ufd3e: ORNATE LEFT PARENTHESIS --> - <string name="more_keys_for_left_parenthesis">[,{,<,\ufd3e</string> - <!-- \ufd3f: ORNATE RIGHT PARENTHESIS --> - <string name="more_keys_for_right_parenthesis">],},>,\ufd3f</string> + <string name="more_keys_for_dash">"ّ,ْ,ٌ,ٓ,ُ,ِ,َ,ً,ـــ|ـ,ٍ,ٔ,ٖ,ٕ,ٰ"</string> + <!-- U+266A: "♪" EIGHTH NOTE --> + <string name="more_keys_for_bullet">♪</string> + <!-- U+2605: "★" BLACK STAR + U+066D: "٭" ARABIC FIVE POINTED STAR --> + <string name="more_keys_for_star">★,٭</string> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- U+0029: ")" RIGHT PARENTHESIS --> + <integer name="keycode_for_left_parenthesis">0x0029</integer> + <!-- U+0028: "(" LEFT PARENTHESIS --> + <integer name="keycode_for_right_parenthesis">0x0028</integer> + <!-- U+FD3E: "﴾" ORNATE LEFT PARENTHESIS + U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS --> + <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!4,﴾|﴿,<|>,{|},[|]</string> + <string name="more_keys_for_right_parenthesis">!fixedColumnOrder!4,﴿|﴾,>|<,}|{,]|[</string> + <!-- U+003E: ">" GREATER-THAN SIGN --> + <integer name="keycode_for_less_than">0x003E</integer> + <!-- U+003C: "<" LESS-THAN SIGN --> + <integer name="keycode_for_greater_than">0x003C</integer> + <!-- U+2264: "≤" LESS-THAN OR EQUAL TO + U+2265: "≥" GREATER-THAN EQUAL TO + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + The following characters don't need BIDI mirroring. + U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <string name="more_keys_for_less_than">!fixedColumnOrder!3,‹|›,≤|≥,«|»</string> + <string name="more_keys_for_greater_than">!fixedColumnOrder!3,›|‹,≥|≤,»|«</string> + <!-- U+005D: "]" RIGHT SQUARE BRACKET --> + <integer name="keycode_for_left_square_bracket">0x005D</integer> + <!-- U+005B: "[" LEFT SQUARE BRACKET --> + <integer name="keycode_for_right_square_bracket">0x005B</integer> + <!-- U+007D: "}" RIGHT CURLY BRACKET --> + <integer name="keycode_for_left_curly_bracket">0x007D</integer> + <!-- U+007B: "{" LEFT CURLY BRACKET --> + <integer name="keycode_for_right_curly_bracket">0x007B</integer> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«,‘,’,‚,‛</string> </resources> diff --git a/java/res/values-ar/donottranslate.xml b/java/res/values-ar/donottranslate.xml new file mode 100644 index 000000000..57de2538b --- /dev/null +++ b/java/res/values-ar/donottranslate.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- Symbols that are suggested between words --> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> +</resources> diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml index dca73659a..46c9d8a91 100644 --- a/java/res/values-ar/strings.xml +++ b/java/res/values-ar/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"لوحة مفاتيح Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"لوحة مفاتيح Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"إعدادات لوحة مفاتيح Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"خيارات الإرسال"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"تصحيح Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"التدقيق الإملائي في Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"التدقيق الإملائي في Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"إعدادات التدقيق الإملائي"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"استخدام بيانات التقريب"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"استخدام خوارزمية تقريب شبيهة بلوحة المفاتيح لإجراء التدقيق الإملائي"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"بحث في أسماء جهات الاتصال"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"يستخدم المدقق الإملائي إدخالات من قائمة جهات الاتصال"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"اهتزاز عند ضغط مفتاح"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"صوت عند الضغط على مفتاح"</string> <string name="popup_on_keypress" msgid="123894815723512944">"انبثاق عند ضغط مفتاح"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"تصحيح النص"</string> <string name="misc_category" msgid="6894192814868233453">"خيارات أخرى"</string> <string name="advanced_settings" msgid="362895144495591463">"الإعدادات المتقدمة"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"خيارات للمستخدمين الخبراء"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"خيارات للخبراء"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"التبديل إلى أسلوب إدخال آخر"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"يغطي مفتاح تبديل اللغات أساليب الإدخال الأخرى أيضًا"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"إيقاف مفتاح تبديل اللغات"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"تأخير إزالة النافذة المنبثقة الأساسية"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"بلا تأخير"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"افتراضي"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"عرض دومًا"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"عرض في وضع رأسي"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"إخفاء دومًا"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"عرض مفتاح الإعدادات"</string> <string name="auto_correction" msgid="4979925752001319458">"التصحيح التلقائي"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"تؤدي المسافة والترقيم إلى تصحيح الكلمات المكتوبة بشكل غير صحيح"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"إيقاف"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : تم الحفظ"</string> <string name="label_go_key" msgid="1635148082137219148">"تنفيذ"</string> <string name="label_next_key" msgid="362972844525672568">"التالي"</string> + <string name="label_previous_key" msgid="1211868118071386787">"السابق"</string> <string name="label_done_key" msgid="2441578748772529288">"تم"</string> <string name="label_send_key" msgid="2815056534433717444">"إرسال"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"أ ب ج"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"لم يتم إدخال نص"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"رمز المفتاح %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"العالي"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"تم تمكين العالي"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"تمكين Caps lock"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift يعمل (انقر للتعطيل)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock يعمل (انقر للتعطيل)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"حذف"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"الرموز"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"أحرف"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"إدخال صوتي"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"وجه مبتسم"</string> <string name="spoken_description_return" msgid="8178083177238315647">"رجوع"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"فاصلة"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"نقطة"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"قوس أيسر"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"قوس أيمن"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"نقطتان"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"فاصلة منقوطة"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"علامة التعجب"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"علامة استفهام"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"علامة الاقتباس المزدوجة"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"علامة الاقتباس المفردة"</string> <string name="spoken_description_dot" msgid="40711082435231673">"نقطة"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"جذر تربيعي"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"باي"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"دلتا"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"علامة تجارية"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"رعاية"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"نجمة"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"جنيه"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"علامة حذف"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"علامة الاقتباس المزدوجة السفلية"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"تم تمكين Shift"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"تم تمكين Caps lock"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"تم تعطيل Shift"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"وضع الرموز"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"وضع الأحرف"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"وضع الهاتف"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"وضع رموز الهاتف"</string> <string name="voice_warning_title" msgid="4419354150908395008">"الإدخال الصوتي"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"الإدخال الصوتي غير معتمد حاليًا للغتك، ولكنه يعمل باللغة الإنجليزية."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"يستخدم الإدخال الصوتي خاصية التعرف على الكلام من Google. تنطبق "<a href="http://m.google.com/privacy">"سياسة خصوصية الجوال"</a>"."</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"تمكين ملاحظات المستخدم"</string> <string name="prefs_description_log" msgid="5827825607258246003">"المساعدة في تحسين محرر طريقة الإرسال هذا من خلال إرسال إحصاءات الاستخدام وتقارير الأعطال تلقائيًا إلى Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"مظهر لوحة المفاتيح"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"الألمانية (QWERTY)"</string> <string name="subtype_en_GB" msgid="88170601942311355">"الإنجليزية (المملكة المتحدة)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"الإنجليزية (الولايات المتحدة)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"وضع سهولة الاستخدام"</string> diff --git a/java/res/values-fr-rCH/donottranslate-more-keys.xml b/java/res/values-be/donottranslate-more-keys.xml index 561c5e52f..1550ddb17 100644 --- a/java/res/values-fr-rCH/donottranslate-more-keys.xml +++ b/java/res/values-be/donottranslate-more-keys.xml @@ -18,9 +18,8 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,â,æ,á,ä,ã,å,ā,ª</string> - <string name="more_keys_for_y">ÿ</string> - <string name="more_keys_for_q">1</string> - <string name="more_keys_for_w">2</string> - <string name="more_keys_for_z">6</string> + <!-- U+045E: "ў" CYRILLIC SMALL LETTER SHORT U --> + <string name="keylabel_for_cyrillic_shcha">ў</string> + <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I --> + <string name="keylabel_for_cyrillic_i">і</string> </resources> diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml index 1ed944caf..ac4433feb 100644 --- a/java/res/values-be/strings.xml +++ b/java/res/values-be/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Клавіятура Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіятура Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Налады клавіятуры Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ўводу"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Папраўкі Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Iнструмент праверкi правапiсу для Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Iнструмент праверкi правапiсу для Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Налады праверкі арфаграфіі"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Выкарыстоўвайць дадзеныя аб блізкасці"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Для праверкі арфаграфіі выкарыстоўваць алгарытм блізкасці, падобны на клавіятуру"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукаць імёны кантактаў"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Модуль праверкі правапісу выкарыстоўвае запісы са спісу кантактаў"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібрацыя пры націску клавіш"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Гук пры націску"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Па націску на клавішы ўсплывае акно"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Выпраўленне тэксту"</string> <string name="misc_category" msgid="6894192814868233453">"Іншыя параметры"</string> <string name="advanced_settings" msgid="362895144495591463">"Адмысловыя налады"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Парам. для дасведч. карыст."</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Функцыi для спецыялістаў"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Затрым. скр. падк. клав."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Няма затрымкі"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Па змаўчанні"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Заўсёды паказваць"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Паказаць у партрэтным рэжыме"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Заўседы хаваць"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Паказаць умоўныя азначэнні налад"</string> <string name="auto_correction" msgid="4979925752001319458">"Аўтамат. выпраўленне"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Прабелы і пунктуацыйныя знакі дазваляюць аўтаматычна выпраўляць памылкова ўведзеныя словы"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Адключаны"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Захаваныя"</string> <string name="label_go_key" msgid="1635148082137219148">"Пачаць"</string> <string name="label_next_key" msgid="362972844525672568">"Далей"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Назад"</string> <string name="label_done_key" msgid="2441578748772529288">"Гатова"</string> <string name="label_send_key" msgid="2815056534433717444">"Адправіць"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Тэкст не ўведзены"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Клавішны код %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Зрух"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Зрух уключаны"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock уключаны"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift уключаны (націснiце, каб адключыць)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock уключаны (націснiце, каб адключыць)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Выдаліць"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Сімвалы"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Літары"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Галасавы ўвод"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Смайлік"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Увод"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Коска"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Кропка"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Адчыняючая дужка"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Дужка, якая зачыняе"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Двукроп\'е"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Кропка з коскай"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Клічнік"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Пытальнік"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двукоссі"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Паўдвукоссі"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Кропка"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратны корань"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Пі"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Дэльта"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Гандлёвая марка"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Працэнт"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Пазначыць"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Фунт"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Шматкроп\'е"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нізкія падвойныя двукоссі"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift уключаны"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock уключаны"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift адключаны"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Рэжым знакаў"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Рэжым лiтар"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Рэжым тэлефона"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Рэжым тэлефонных знакаў"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Галасавы ўвод"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Галасавы ўвод пакуль не падтрымліваецца для вашай мовы, але працуе на англійскай мове."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Галасавы набор выкарыстоўвае распазнанне гаворкі Google. Ужываецца "<a href="http://m.google.com/privacy">"палiтыка прыватнасцi для мабiльных прылад"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Уключыць зваротную сувязь з карыстальнікамі"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Дапамажыце палепшыць гэты рэдактар метаду ўводу, аўтаматычна адпраўляючы статыстыку выкарыстання і справаздачы аб збоях Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Тэма клавіятуры"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Нямецкая QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Англійская (ЗК)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Англійская (ЗША)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Рэжым даследвання выкарыстальнасці"</string> diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml index 30fe132d8..f3b9347a4 100644 --- a/java/res/values-bg/strings.xml +++ b/java/res/values-bg/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Клавиатура на Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура на Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Настройки на клавиатурата на Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Опции за въвеждане"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Корекция на Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Програма за правописна проверка за Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Програма за правописна проверка за Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройки за проверка на правописа"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Използване на близост"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Проверка на правописа: Използвайте алгоритъм за близост"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Търсене на имена"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"За проверка на правописа се ползват записи от списъка с контакти"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Да вибрира при натискане на клавиш"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натискане на клавиш"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Изскачащ прозорец при натискане на клавиш"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Корекция на текста"</string> <string name="misc_category" msgid="6894192814868233453">"Други опции"</string> <string name="advanced_settings" msgid="362895144495591463">"Разширени настройки"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Опции за потребителите експерти"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Опции за експерти"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Отхвърляне на подсказката"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без задържане"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По подразбиране"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Винаги да се показва"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Показване с вертикална ориентация"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Винаги да се скрива"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Показване на клавиша за настройки"</string> <string name="auto_correction" msgid="4979925752001319458">"Автоко"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Клавишът за интервал и пунктуация авт. поправя сгрешени думи"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Изкл."</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Запазено"</string> <string name="label_go_key" msgid="1635148082137219148">"Старт"</string> <string name="label_next_key" msgid="362972844525672568">"Напред"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Пред."</string> <string name="label_done_key" msgid="2441578748772529288">"Готово"</string> <string name="label_send_key" msgid="2815056534433717444">"Изпращане"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Няма въведен текст"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Код на клавишa %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"„Shift“ е активиран"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"„Caps Lock“ е активиран"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"„Shift“ е включен (докоснете за деактивиране)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"„Caps lock“ е включен (докоснете за деактивиране)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Символи"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Букви"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Гласово въвеждане"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Усмивка"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Запетая"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Точка"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Лява кръгла скоба"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Дясна кръгла скоба"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Двоеточие"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Точка и запетая"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Удивителен знак"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Въпросителен знак"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двойни кавички"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Единични кавички"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Корен квадратен"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Пи"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Делта"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Запазена марка"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"По адрес"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Звездичка"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Диез"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Многоточие"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Долни двойни кавички"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"„Shift“ е активиран"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"„Caps Lock“ е активиран"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"„Shift“ е деактивиран"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Режим за символи"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Режим за букви"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Режим за телефон"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Режим за символи на телефона"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Гласово въвеждане"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"За вашия език понастоящем не се поддържа гласово въвеждане, но можете да го използвате на английски."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Гласовото въвеждане използва функцията на Google за разпознаване на говор. В сила е "<a href="http://m.google.com/privacy">"Декларацията за поверителност за мобилни устройства"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Активиране на отзивите от потребителите"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Помогнете за подобряването на този редактор за въвеждане чрез автоматично изпращане до Google на статистически данни за употребата и сигнали за сривове."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Тема на клавиатурата"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"немски, „QWERTY“"</string> <string name="subtype_en_GB" msgid="88170601942311355">"английски (Великобритания)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"английски (САЩ)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за изучаване на използваемостта"</string> diff --git a/java/res/values-ca/donottranslate-more-keys.xml b/java/res/values-ca/donottranslate-more-keys.xml index bd9fb7ccd..baa23bf9c 100644 --- a/java/res/values-ca/donottranslate-more-keys.xml +++ b/java/res/values-ca/donottranslate-more-keys.xml @@ -18,12 +18,56 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,á,ä,â,ã,å,ą,æ,ā,ª</string> - <string name="more_keys_for_e">3,è,é,ë,ê,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,ï,ì,î,į,ī</string> - <string name="more_keys_for_o">9,ò,ó,ö,ô,õ,ø,œ,ō,º</string> - <string name="more_keys_for_u">7,ú,ü,ù,û,ū</string> - <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_c">ç,ć,č</string> - <string name="more_keys_for_l">ŀ,ł</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + U+00E6: "æ" LATIN SMALL LETTER AE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00AA: "ª" FEMININE ORDINAL INDICATOR --> + <string name="more_keys_for_a">à,á,ä,â,ã,å,ą,æ,ā,ª</string> + <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">è,é,ë,ê,ę,ė,ē</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,ï,ì,î,į,ī</string> + <!-- U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00BA: "º" MASCULINE ORDINAL INDICATOR --> + <string name="more_keys_for_o">ò,ó,ö,ô,õ,ø,œ,ō,º</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,ù,û,ū</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ç,ć,č</string> + <!-- U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> + <string name="more_keys_for_l">ŀ,ł</string> </resources> diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml index a58d8faa9..619dc38af 100644 --- a/java/res/values-ca/strings.xml +++ b/java/res/values-ca/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Teclat Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclat d\'Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Configuració del teclat d\'Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opcions d\'entrada"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Correcció d\'Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortogràfic d\'Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortogràfic d\'Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuració de la correcció ortogràfica"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilitza les dades de proximitat"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilitza un algorisme de proximitat similar al teclat per comprovar l\'ortografia"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca noms de contactes"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortogràfic utilitza entrades de la llista de cont."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"So en prémer una tecla"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Finestra emergent en prémer un botó"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Correcció de text"</string> <string name="misc_category" msgid="6894192814868233453">"Altres opcions"</string> <string name="advanced_settings" msgid="362895144495591463">"Configuració avançada"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcions per a usuaris experts"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcions per a experts"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retard d\'om. em. de tecla"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sense retard"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostra en mode vertical"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Amaga sempre"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostra la tecla de configuració"</string> <string name="auto_correction" msgid="4979925752001319458">"Correcció automàtica"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Barra espaiadora i punt. correg. autom. paraules mal escrites"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactiva"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: desada"</string> <string name="label_go_key" msgid="1635148082137219148">"Vés"</string> <string name="label_next_key" msgid="362972844525672568">"Següent"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> <string name="label_done_key" msgid="2441578748772529288">"Fet"</string> <string name="label_send_key" msgid="2815056534433717444">"Envia"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"No s\'ha introduït cap text"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Clau de codi %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Maj"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Maj activat"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloq Maj activat"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maj activat (pica per desactivar)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Bloq Maj activat (pica per desactivar)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Supr"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbols"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Lletres"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de veu"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Cara somrient"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Retorn"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punt"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parèntesi esquerre"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parèntesi dret"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Coma"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Punt i coma"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signe d\'admiració"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signe d\'interrogació"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Cometes dobles"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Cometes simples"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Arrel quadrada"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Percentatge"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Destaca"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Coixinet"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Punts suspensius"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Cometes angulars"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maj activat"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloq Maj activat"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maj desactivat"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode de símbols"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode de lletres"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode de telèfon"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode de símbols de telèfon"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de veu"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualment, l\'entrada de veu no és compatible amb el vostre idioma, però funciona en anglès."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"L\'entrada de veu utilitza el reconeixement de veu de Google. S\'hi aplica la "<a href="http://m.google.com/privacy">"Política de privadesa de Google per a mòbils"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Activa els comentaris de l\'usuari"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ajuda a millorar aquest editor de mètodes d\'entrada enviant automàticament estadístiques d\'ús i informes de bloqueigs a Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclat"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY alemany"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Anglès (Regne Unit)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Anglès (EUA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'estudi d\'usabilitat"</string> diff --git a/java/res/values-cs/donottranslate-more-keys.xml b/java/res/values-cs/donottranslate-more-keys.xml index 70b3f3ee7..9af6794df 100644 --- a/java/res/values-cs/donottranslate-more-keys.xml +++ b/java/res/values-cs/donottranslate-more-keys.xml @@ -18,17 +18,70 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,à,â,ä,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,é,ě,è,ê,ë,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,î,ï,ì,į,ī</string> - <string name="more_keys_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string> - <string name="more_keys_for_u">7,ú,ů,û,ü,ù,ū</string> - <string name="more_keys_for_s">š,ß,ś</string> - <string name="more_keys_for_n">ň,ñ,ń</string> - <string name="more_keys_for_c">č,ç,ć</string> - <string name="more_keys_for_y">ý,ÿ</string> - <string name="more_keys_for_d">ď</string> - <string name="more_keys_for_r">4,ř</string> - <string name="more_keys_for_t">5,ť</string> - <string name="more_keys_for_z">6,ž,ź,ż</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">á,à,â,ä,æ,ã,å,ā</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+011B: "ě" LATIN SMALL LETTER E WITH CARON + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,ě,è,ê,ë,ę,ė,ē</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,î,ï,ì,į,ī</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ó,ö,ô,ò,õ,œ,ø,ō</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ů,û,ü,ù,ū</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE --> + <string name="more_keys_for_s">š,ß,ś</string> + <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ň,ñ,ń</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ç,ć</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON --> + <string name="more_keys_for_d">ď</string> + <!-- U+0159: "ř" LATIN SMALL LETTER R WITH CARON --> + <string name="more_keys_for_r">ř</string> + <!-- U+0165: "ť" LATIN SMALL LETTER T WITH CARON --> + <string name="more_keys_for_t">ť</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE --> + <string name="more_keys_for_z">ž,ź,ż</string> </resources> diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index d57ccaa28..6305f6e64 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Klávesnice Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnice Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Nastavení klávesnice Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávání textu a dat"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Opravy Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavení kontroly pravopisu"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Použít údaje o blízkosti"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Při kontrole pravopisu uvažovat blízkost písmen na klávesnici"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhledat kontakty"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používá záznamy z vašeho seznamu kontaktů."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk při stisku klávesy"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Zobrazit znaky při stisku klávesy"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Oprava textu"</string> <string name="misc_category" msgid="6894192814868233453">"Další možnosti"</string> <string name="advanced_settings" msgid="362895144495591463">"Pokročilá nastavení"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti pro zkušené uživatele"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti pro odborníky"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna kláv."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez prodlevy"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovat"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Zobrazit v režimu na výšku"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývat"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Zobrazit klávesu Nastavení"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatické opravy"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Stisknutím mezerníku a interpunkce se automaticky opravují chybně napsaná slova"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Vypnuto"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Uloženo"</string> <string name="label_go_key" msgid="1635148082137219148">"Přejít"</string> <string name="label_next_key" msgid="362972844525672568">"Další"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Před."</string> <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> <string name="label_send_key" msgid="2815056534433717444">"Odeslat"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Není zadán žádný text"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kód klávesy %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Klávesa Shift je aktivní"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Klávesa Caps Lock je aktivní"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Klávesa Shift je zapnutá (vypnete ji klepnutím)."</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Klávesa Caps Lock je zapnutá (vypnete ji klepnutím)."</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboly"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Písmena"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Hlasový vstup"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smajlík"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Čárka"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Tečka"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Levá závorka"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Pravá závorka"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dvojtečka"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Středník"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Vykřičník"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Otazník"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Uvozovky"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Apostrof"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Tečka"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Odmocnina"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pí"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Ochranná známka"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Procento"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Hvězdička"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Libra"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tři tečky"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Uvozovky dole"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Klávesa Shift je aktivní"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Klávesa Caps Lock je aktivní"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Klávesa Shift je neaktivní"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Režim symbolů"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Režim písmen"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Režim telefonu"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Režim telefonních symbolů"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Hlasový vstup"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Pro váš jazyk aktuálně není hlasový vstup podporován, ale funguje v angličtině."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Hlasový vstup používá rozpoznávání hlasu Google a vztahují se na něj "<a href="http://m.google.com/privacy">"Zásady ochrany osobních údajů pro mobilní služby"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivovat zasílání statistik užívání a zpráv o selhání"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasíláním statistik o užívání editoru zadávání dat a zpráv o jeho selhání do Googlu můžete přispět k vylepšení tohoto nástroje."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"němčina (QWERTY)"</string> <string name="subtype_en_GB" msgid="88170601942311355">"angličtina (Spojené království)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"angličtina (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim studie použitelnosti"</string> diff --git a/java/res/values-da/donottranslate-more-keys.xml b/java/res/values-da/donottranslate-more-keys.xml index 12c1ebfe1..739ab09e7 100644 --- a/java/res/values-da/donottranslate-more-keys.xml +++ b/java/res/values-da/donottranslate-more-keys.xml @@ -18,18 +18,54 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,ä,à,â,ã,ā</string> - <string name="more_keys_for_e">3,é,ë</string> - <string name="more_keys_for_i">8,í,ï</string> - <string name="more_keys_for_o">9,ó,ô,ò,õ,œ,ō</string> - <string name="more_keys_for_u">7,ú,ü,û,ù,ū</string> - <string name="more_keys_for_s">ß,ś,š</string> - <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_y">6,ý,ÿ</string> - <string name="more_keys_for_d">ð</string> - <string name="more_keys_for_l">ł</string> - <string name="keylabel_for_scandinavia_row2_10">æ</string> - <string name="keylabel_for_scandinavia_row2_11">ø</string> - <string name="more_keys_for_scandinavia_row2_10">ä</string> - <string name="more_keys_for_scandinavia_row2_11">ö</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">á,ä,à,â,ã,ā</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS --> + <string name="more_keys_for_e">é,ë</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS --> + <string name="more_keys_for_i">í,ï</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ó,ô,ò,õ,œ,ō</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,û,ù,ū</string> + <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ß,ś,š</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+00F0: "ð" LATIN SMALL LETTER ETH --> + <string name="more_keys_for_d">ð</string> + <!-- U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> + <string name="more_keys_for_l">ł</string> + <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE --> + <string name="keylabel_for_scandinavia_row1_11">å</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="keylabel_for_scandinavia_row2_10">æ</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="keylabel_for_scandinavia_row2_11">ø</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="more_keys_for_scandinavia_row2_10">ä</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="more_keys_for_scandinavia_row2_11">ö</string> </resources> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index b91acaa90..df5dfa58b 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-tastatur"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android-tastatur-indstillinger"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Indstillinger for input"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-rettelse"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontrol"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontrol (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Indstillinger for stavekontrol"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Brug nærhedsdata"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Brug en tastaturlignende nærhedsalgoritme til stavekontrol"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå kontaktnavne op"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruger poster fra listen over kontaktpersoner"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetryk"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop op ved tastetryk"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Tekstkorrigering"</string> <string name="misc_category" msgid="6894192814868233453">"Andre valgmuligheder"</string> <string name="advanced_settings" msgid="362895144495591463">"Avancerede indstillinger"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Muligheder for ekspertbrugere"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Muligheder for eksperter"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Forsink. afvis. af taste-pop op"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ingen forsink."</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis altid"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Vis i portrættilstand"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul altid"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Vis indstillingsnøgle"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatisk retning"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Mellemrumstast og tegnsætning retter automatisk forkerte ord"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Fra"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Gemt"</string> <string name="label_go_key" msgid="1635148082137219148">"Gå"</string> <string name="label_next_key" msgid="362972844525672568">"Næste"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> <string name="label_done_key" msgid="2441578748772529288">"Udfør"</string> <string name="label_send_key" msgid="2815056534433717444">"Send"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Der er ingen indtastet tekst"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Tastekode %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift-tast"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift-tasten er aktiveret"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock er aktiveret"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift er slået til (tryk for at deaktivere)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock er slået til (tryk for at deaktivere)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Slet"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Bogstaver"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Stemmeinput"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Tilbage"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punktum"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Venstre parentes"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Højre parentes"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Udråbstegn"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Spørgsmålstegn"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dobbelt anførselstegn"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkelt anførselstegn"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punktum"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrod"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Varemærke"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"De bedste hilsner"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Stjerne"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pund"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lave dobbelte anførelsestegn"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift er aktiveret"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock er aktiveret"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift er deaktiveret"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symboltilstand"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bogstavtilstand"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefontilstand"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefonsymboltilstand"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Stemmeinput"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmeinput understøttes i øjeblikket ikke for dit sprog, men fungerer på engelsk."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Stemmeinput anvender Googles stemmegenkendelse. "<a href="http://m.google.com/privacy">"Fortrolighedspolitikken for mobilenheder"</a>" gælder."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brugerfeedback"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Vær med til at forbedre denne inputmetode ved at sende anvendelsesstatistikker og rapporter om nedbrud til Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Tysk QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tilstand for brugsstudie"</string> diff --git a/java/res/values-de/donottranslate-more-keys.xml b/java/res/values-de/donottranslate-more-keys.xml index 80aa32ae2..562e574eb 100644 --- a/java/res/values-de/donottranslate-more-keys.xml +++ b/java/res/values-de/donottranslate-more-keys.xml @@ -18,12 +18,37 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ä,â,à,á,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,ė</string> - <string name="more_keys_for_o">9,ö,ô,ò,ó,õ,œ,ø,ō</string> - <string name="more_keys_for_u">7,ü,û,ù,ú,ū</string> - <string name="more_keys_for_s">ß,ś,š</string> - <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_y"></string> - <string name="more_keys_for_z">6</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">ä,â,à,á,æ,ã,å,ā</string> + <!-- U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE --> + <string name="more_keys_for_e">ė</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ö,ô,ò,ó,õ,œ,ø,ō</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ü,û,ù,ú,ū</string> + <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ß,ś,š</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> </resources> diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index d329f3271..a2584bc2f 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-Tastatur"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-Tastatur (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android-Tastatureinstellungen"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Eingabeoptionen"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Rechtschreibprüfung für Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-Rechtschreibprüfung"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-Rechtschreibprüfung (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Einstellungen für Rechtschreibprüfung"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Näherungsdaten verwenden"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Tastaturähnl. Abstandsalgorith. für Rechtschreibprüfung verwenden"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktnamen prüfen"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rechtschreibprüfung verwendet Einträge aus Ihrer Kontaktliste."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Ton bei Tastendruck"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bei Tastendruck"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Textkorrektur"</string> <string name="misc_category" msgid="6894192814868233453">"Sonstige Optionen"</string> <string name="advanced_settings" msgid="362895144495591463">"Erweiterte Einstellungen"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Optionen für Experten"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Optionen für Experten"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tasten-Pop-up"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Keine Verzögerung"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Immer anzeigen"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Im Hochformat anzeigen"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nie anzeigen"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Taste für Einstellungen"</string> <string name="auto_correction" msgid="4979925752001319458">"Autokorrektur"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Korrektur fehlerhafter Wörter durch Leertaste und Satzzeichen"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Aus"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: gespeichert"</string> <string name="label_go_key" msgid="1635148082137219148">"Los"</string> <string name="label_next_key" msgid="362972844525672568">"Weiter"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Vorh."</string> <string name="label_done_key" msgid="2441578748772529288">"Fertig"</string> <string name="label_send_key" msgid="2815056534433717444">"Senden"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Kein Text eingegeben"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Tastencode %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Umschalttaste"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Umschalttaste aktiviert"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Feststelltaste aktiviert"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Umschalttaste aktiviert (zum Deaktivieren berühren)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Feststelltaste aktiviert (zum Deaktivieren berühren)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Entf"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbole"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Buchstaben"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Spracheingabe"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Eingabe"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Öffnende Klammer"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Schließende Klammer"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Doppelpunkt"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ausrufezeichen"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Fragezeichen"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Anführungszeichen"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Einfaches Anführungszeichen"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Aufzählungspunkt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Quadratwurzel"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Sternchen"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Raute"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Auslassungszeichen"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Anführungszeichen unten"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Umschalttaste aktiviert"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Feststelltaste aktiviert"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Umschalttaste deaktiviert"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolmodus"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Buchstabenmodus"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonmodus"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefon-Symbolmodus"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Spracheingabe"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spracheingaben werden zurzeit nicht für Ihre Sprache unterstützt, funktionieren jedoch in Englisch."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Die Spracheingabe verwendet die Spracherkennung von Google. Es gelten die "<a href="http://m.google.com/privacy">"Google Mobile-Datenschutzbestimmungen"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Nutzer-Feedback aktivieren"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Tragen Sie zur Verbesserung dieses Eingabemethodeneditors bei, indem Sie automatisch Nutzungsstatistiken und Absturzberichte an Google senden."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturdesign"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Deutsche QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Englisch (Großbritannien)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Englisch (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus der Studie zur Benutzerfreundlichkeit"</string> diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index 6fe191ee7..1d6fc10f4 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Πληκτρολόγιο Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Πληκτρολόγιο Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Ρυθμίσεις πληκτρολογίου Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Επιλογές εισόδου"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Διόρθωση Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Ορθογραφικός έλεγχος Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Ορθογραφικός έλεγχος Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ρυθμίσεις ορθογραφικού ελέγχου"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Χρ. δεδ. εγγύτ."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Χρησ. αλγόρ. εγγύτ. τύπου πληκτρ., για ορθ. έλεγχο"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Αναζήτηση ονομάτων επαφών"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Ο ορθογρ. έλεγχος χρησιμοπ. καταχωρίσεις από τη λίστα επαφών σας"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Δόνηση κατά το πάτημα πλήκτρων"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Ήχος κατά το πάτημα πλήκτρων"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Εμφάνιση με το πάτημα πλήκτρου"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Διόρθωση κειμένου"</string> <string name="misc_category" msgid="6894192814868233453">"Άλλες επιλογές"</string> <string name="advanced_settings" msgid="362895144495591463">"Σύνθετες ρυθμίσεις"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Επιλογές για έμπειρους χρήστες"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Επιλογές για έμπειρους χρήστες"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Χρόνος εξαφ. αναδ. παραθ."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Χωρίς καθυστέρ."</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Προεπιλογή"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Να εμφανίζεται πάντα"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Εμφάνιση σε λειτουργία κατακόρυφης προβολής"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Πάντα απόκρυψη"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Εμφάνιση πλήκτρου ρυθμίσεων"</string> <string name="auto_correction" msgid="4979925752001319458">"Αυτόματη διόρθωση"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Τα πλήκτρα διαστήματος και στίξης διορθ. αυτόμ. λάθος λέξεις"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Απενεργοποίηση"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Αποθηκεύτηκε"</string> <string name="label_go_key" msgid="1635148082137219148">"Μετ."</string> <string name="label_next_key" msgid="362972844525672568">"Επόμενο"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Προηγ"</string> <string name="label_done_key" msgid="2441578748772529288">"Τέλος"</string> <string name="label_send_key" msgid="2815056534433717444">"Αποστολή"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ΑΒΓ"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Δεν υπάρχει κείμενο"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Κωδικός πλήκτρου %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift ενεργοποιημένο"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock ενεργοποιημένο"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Το Shift είναι ενεργοποιημένο (πατήστε για απενεργοποίηση)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Το Caps lock είναι ενεργοποιημένο (πατήστε για απενεργοποίηση)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Πλήκτρο Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Σύμβολα"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Γράμματα:"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Μικρόφωνο"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Πλήκτρο Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Κόμμα"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Τελεία"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Αριστερή παρένθεση"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Δεξιά παρένθεση"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Άνω και κάτω τελεία"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Ερωτηματικό"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Θαυμαστικό"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ερωτηματικό"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Διπλά εισαγωγικά"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Μονό εισαγωγικό"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Κουκκίδα"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Τετραγωνική ρίζα"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"πι"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Δέλτα"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Εμπορικό σήμα"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Υπεύθυνος"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Αστερίσκος"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Δίεση"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Αποσιωπητικά"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Χαμηλό διπλό εισαγωγικό"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Το Shift ενεργοποιημένο"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Το Caps lock είναι ενεργοποιημένο"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Το Shift είναι απενεργοποιημένο"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Λειτουργία συμβόλων"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Λειτουργία γραμμάτων"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Λειτουργία τηλεφώνου"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Λειτουργία συμβόλων τηλεφώνου"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Φωνητική είσοδος"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Η φωνητική είσοδος δεν υποστηρίζεται αυτή τη στιγμή για τη γλώσσα σας, ωστόσο λειτουργεί στα Αγγλικά."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Οι φωνητικές εντολές χρησιμοποιούν την τεχνολογία αναγνώρισης φωνής της Google. Ισχύει "<a href="http://m.google.com/privacy">"η Πολιτική Απορρήτου για κινητά"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Ενεργοποίηση σχολίων χρηστών"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Βοηθήστε μας να βελτιώσουμε αυτό το πρόγραμμα επεξεργασίας μεθόδου εισόδου στέλνοντας αυτόματα στατιστικά στοιχεία και αναφορές σφαλμάτων στην Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Θέμα πληκτρολογίου"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Γερμανικά QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Αγγλικά (Η.Β.)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Αγγλικά (Η.Π.Α)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Λειτουργία μελέτης χρηστικότητας"</string> diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml index a7d50860c..53d025213 100644 --- a/java/res/values-en-rGB/strings.xml +++ b/java/res/values-en-rGB/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android keyboard"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android keyboard settings"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Input options"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android correction"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android spell checker"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android spell checker (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Spellchecking settings"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Use proximity data"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Use a keyboard-like proximity algorithm for spellchecking"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on key-press"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Sound on key-press"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"Text correction"</string> <string name="misc_category" msgid="6894192814868233453">"Other Options"</string> <string name="advanced_settings" msgid="362895144495591463">"Advanced settings"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Options for expert users"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Options for experts"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key covers other input methods too"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suppress language switch key"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Always show"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Show on portrait mode"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Show settings key"</string> <string name="auto_correction" msgid="4979925752001319458">"Auto-correction"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Spacebar and punctuation correct mistyped words automatically"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Saved"</string> <string name="label_go_key" msgid="1635148082137219148">"Go"</string> <string name="label_next_key" msgid="362972844525672568">"Next"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Prev"</string> <string name="label_done_key" msgid="2441578748772529288">"Done"</string> <string name="label_send_key" msgid="2815056534433717444">"Send"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"No text entered"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Key code %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift enabled"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock enabled"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift on (tap to disable)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock on (tap to disable)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbols"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Voice input"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley face"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Comma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Full stop"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Left parenthesis"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Right parenthesis"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Colon"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semi-colon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Exclamation mark"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Question mark"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Double quote"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Single quote"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Dot"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Star"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pound"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Low double quote"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift enabled"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock enabled"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift disabled"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbols mode"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Letters mode"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Phone mode"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Phone symbols mode"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Voice input"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Voice input is not currently supported for your language, but does work in English."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Voice input uses Google\'s speech recognition. "<a href="http://m.google.com/privacy">"The Mobile Privacy Policy"</a>" applies."</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Enable user feedback"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Help improve this input method editor by sending usage statistics and crash reports automatically to Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"German QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Usability study mode"</string> diff --git a/java/res/values-en/additional-proximitychars.xml b/java/res/values-en/additional-proximitychars.xml new file mode 100644 index 000000000..a5ff4a979 --- /dev/null +++ b/java/res/values-en/additional-proximitychars.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <string-array name="additional_proximitychars"> + <!-- Empty entry terminates the proximity chars array. --> + + <!-- Additional proximity chars for a --> + <item>a</item> + <item>e</item> + <item>i</item> + <item>o</item> + <item>u</item> + <item></item> + <!-- Additional proximity chars for e --> + <item>e</item> + <item>a</item> + <item>i</item> + <item>o</item> + <item>u</item> + <item></item> + <!-- Additional proximity chars for i --> + <item>i</item> + <item>a</item> + <item>e</item> + <item>o</item> + <item>u</item> + <item></item> + <!-- Additional proximity chars for o --> + <item>o</item> + <item>a</item> + <item>e</item> + <item>i</item> + <item>u</item> + <item></item> + <!-- Additional proximity chars for u --> + <item>u</item> + <item>a</item> + <item>e</item> + <item>i</item> + <item>o</item> + <item></item> + </string-array> + +</resources> diff --git a/java/res/values-en/donottranslate-more-keys.xml b/java/res/values-en/donottranslate-more-keys.xml index bc26c6aa0..9073d3b4f 100644 --- a/java/res/values-en/donottranslate-more-keys.xml +++ b/java/res/values-en/donottranslate-more-keys.xml @@ -19,11 +19,11 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="more_keys_for_a">à,á,â,ä,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,è,é,ê,ë,ē</string> - <string name="more_keys_for_i">8,î,ï,í,ī,ì</string> - <string name="more_keys_for_o">9,ô,ö,ò,ó,œ,ø,ō,õ</string> + <string name="more_keys_for_e">è,é,ê,ë,ē</string> + <string name="more_keys_for_i">î,ï,í,ī,ì</string> + <string name="more_keys_for_o">ô,ö,ò,ó,œ,ø,ō,õ</string> <string name="more_keys_for_s">ß</string> - <string name="more_keys_for_u">7,û,ü,ù,ú,ū</string> + <string name="more_keys_for_u">û,ü,ù,ú,ū</string> <string name="more_keys_for_n">ñ</string> <string name="more_keys_for_c">ç</string> </resources> diff --git a/java/res/values-en/whitelist.xml b/java/res/values-en/whitelist.xml index f929cec23..fd79999bf 100644 --- a/java/res/values-en/whitelist.xml +++ b/java/res/values-en/whitelist.xml @@ -422,6 +422,10 @@ <item>needn\'t</item> <item>255</item> + <item>nit</item> + <item>not</item> + + <item>255</item> <item>oclock</item> <item>o\'clock</item> diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index 95e309ff7..e111bdd1a 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Teclado de Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado de Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Configuración de teclado de Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones de entrada"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Corrector de Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortográfico de Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortográfico de Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configuración del corrector ortográfico"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilizar datos de prox."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilizar algoritmo de prox. de teclado para corrector ortográfico"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres contactos"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Sonar al pulsar las teclas"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Aviso emergente al pulsar tecla"</string> @@ -34,13 +36,19 @@ <string name="correction_category" msgid="2236750915056607613">"Corrección de texto"</string> <string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string> <string name="advanced_settings" msgid="362895144495591463">"Configuración avanzada"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opciones para usuarios expertos"</string> - <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Demora en rechazo de ventana emergente de clave"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> + <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso en rechazo de alerta de tecla"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin demora"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string> <string name="use_contacts_dict" msgid="4435317977804180815">"Sugerir nombres de contacto"</string> <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Usar nombres de los contactos para sugerencias y correcciones"</string> - <string name="enable_span_insert" msgid="7204653105667167620">"Habilitar correcciones"</string> + <string name="enable_span_insert" msgid="7204653105667167620">"Activar correcciones"</string> <string name="enable_span_insert_summary" msgid="2947317657871394467">"Establecer sugerencias para realizar correcciones"</string> <string name="auto_cap" msgid="1719746674854628252">"Mayúsculas automáticas"</string> <string name="configure_dictionaries_title" msgid="4238652338556902049">"Diccionarios complementarios"</string> @@ -50,9 +58,8 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar en modo retrato"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de configuración"</string> <string name="auto_correction" msgid="4979925752001319458">"Corrección automática"</string> - <string name="auto_correction_summary" msgid="5625751551134658006">"La barra espaciadora y puntuación insertan automáticamente las palabras corregidas"</string> + <string name="auto_correction_summary" msgid="5625751551134658006">"La barra espaciadora y las teclas de puntuación insertan automáticamente la palabra corregida"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactivado"</string> <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderado"</string> <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Total"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> <string name="label_next_key" msgid="362972844525672568">"Siguiente"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> <string name="label_done_key" msgid="2441578748772529288">"Hecho"</string> <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"No se ingresó texto."</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Clave de código %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Mayús"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Mayús habilitada"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloqueo de mayúsculas habilitado"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Se activó el modo Mayúscula (toca para desactivarlo)."</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Se activó el bloqueo de mayúsculas (toca para desactivarlo)."</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Borrar"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Carita sonriente"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Volver"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paréntesis de apertura"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paréntesis de cierre"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dos puntos"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto y coma"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signo de admiración"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signo de interrogación"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Comillas dobles"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Comillas simples"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Raíz cuadrada"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marca registrada"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"En atención de"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Destacar"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Numeral"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Comillas bajas"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Se activó el modo Mayúscula."</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Se activó el bloqueo de mayúsculas."</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Se desactivó el modo Mayúscula"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo Símbolos"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo Letras"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo Teléfono"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo Símbolos del teléfono"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Entrada por voz"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La entrada por voz no está admitida en tu idioma, pero sí funciona en inglés."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La entrada de voz usa el reconocimiento de voz de Google. "<a href="http://m.google.com/privacy">"Se aplica la política de privacidad para"</a>" celulares."</string> @@ -128,7 +124,7 @@ <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" La próxima vez intenta decir la puntuación como \"punto\", \"coma\" o \"signo de pregunta\"."</string> <string name="cancel" msgid="6830980399865683324">"Cancelar"</string> <string name="ok" msgid="7898366843681727667">"Aceptar"</string> - <string name="voice_input" msgid="3583258583521397548">"Clave de entrada de voz"</string> + <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada por voz"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En el teclado principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En el teclado de símbolos"</string> <string name="voice_input_modes_off" msgid="3745699748218082014">"Desactivado"</string> @@ -141,10 +137,9 @@ <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string> <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tocar de nuevo para guardar"</string> <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string> - <string name="prefs_enable_log" msgid="6620424505072963557">"Habilitar los comentarios del usuario"</string> + <string name="prefs_enable_log" msgid="6620424505072963557">"Activar los comentarios del usuario"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto al enviar las estadísticas de uso y los informes de error a Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclado"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY alemán"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EE.UU.)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string> diff --git a/java/res/values-es/donottranslate-more-keys.xml b/java/res/values-es/donottranslate-more-keys.xml index d5a8ed19d..f56b1d54f 100644 --- a/java/res/values-es/donottranslate-more-keys.xml +++ b/java/res/values-es/donottranslate-more-keys.xml @@ -18,12 +18,56 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,à,ä,â,ã,å,ą,æ,ā,ª</string> - <string name="more_keys_for_e">3,é,è,ë,ê,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,ï,ì,î,į,ī</string> - <string name="more_keys_for_o">9,ó,ò,ö,ô,õ,ø,œ,ō,º</string> - <string name="more_keys_for_u">7,ú,ü,ù,û,ū</string> - <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_c">ç,ć,č</string> - <string name="more_keys_for_punctuation">"\\,,\?,!,¿,¡,:,-,\',\",),(,/,;,+,&,\@"</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + U+00E6: "æ" LATIN SMALL LETTER AE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00AA: "ª" FEMININE ORDINAL INDICATOR --> + <string name="more_keys_for_a">á,à,ä,â,ã,å,ą,æ,ā,ª</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,è,ë,ê,ę,ė,ē</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,ï,ì,î,į,ī</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00BA: "º" MASCULINE ORDINAL INDICATOR --> + <string name="more_keys_for_o">ó,ò,ö,ô,õ,ø,œ,ō,º</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,ù,û,ū</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ç,ć,č</string> + <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK + U+00BF: "¿" INVERTED QUESTION MARK --> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!7,#,-,¡,!,¿,\\,,\?,\\%,+,;,:,/,(,),\@,&,\",\'"</string> </resources> diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index fcd65e1fc..2018c557f 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Teclado de Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Ajustes del teclado de Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opciones introducción texto"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Corrector de Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Corrector ortográfico de Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corrector ortográfico de Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ajustes del corrector ortográfico"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Usar datos de proximidad"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usar algoritmo de proximidad de teclado para corregir la ortografía"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nombres de contactos"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"El corrector ortográfico usa entradas de tu lista de contactos."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Sonido al pulsar tecla"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up al pulsar tecla"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Corrección ortográfica"</string> <string name="misc_category" msgid="6894192814868233453">"Otras opciones"</string> <string name="advanced_settings" msgid="362895144495591463">"Ajustes avanzados"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opciones para usuarios expertos"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso de rechazo"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar en modo vertical"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de ajustes"</string> <string name="auto_correction" msgid="4979925752001319458">"Autocorrección"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Pulsar la tecla de espacio o punto para corregir errores"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactivada"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> <string name="label_next_key" msgid="362972844525672568">"Sig."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Anterior"</string> <string name="label_done_key" msgid="2441578748772529288">"Ok"</string> <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"No se ha introducido texto."</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Código del teclado: %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Mayús"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Tecla Mayús habilitada"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Bloq Mayús habilitado"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Mayúsculas activadas (tocar para inhabilitar)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Bloqueo de mayúsculas activado (tocar para inhabilitar)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Suprimir"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Emoticono"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Tecla Intro"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Coma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paréntesis de apertura"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paréntesis de cierre"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dos puntos"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto y coma"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Signo de exclamación"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Signo de interrogación"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Comillas dobles"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Comillas simples"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punto"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Raíz cuadrada"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Porcentaje"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Almohadilla"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Puntos suspensivos"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Comillas dobles bajas"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Mayúsculas habilitadas"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Bloqueo de mayúsculas habilitado"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Mayúsculas inhabilitadas"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de letras"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de teléfono"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de teléfono"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Introducción de voz"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente la introducción de voz no está disponible en tu idioma, pero se puede utilizar en inglés."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La entrada de voz utiliza el reconocimiento de voz de Google. Se aplica la "<a href="http://m.google.com/privacy">"Política de privacidad de Google para móviles"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Habilitar comentarios de usuarios"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ayuda a mejorar este editor de método de introducción de texto enviando estadísticas de uso e informes de error a Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY alemán"</string> <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudio de usabilidad"</string> diff --git a/java/res/values-et/donottranslate-more-keys.xml b/java/res/values-et/donottranslate-more-keys.xml new file mode 100644 index 000000000..be66b42f5 --- /dev/null +++ b/java/res/values-et/donottranslate-more-keys.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+00E6: "æ" LATIN SMALL LETTER AE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK --> + <string name="more_keys_for_a">ä,ā,à,á,â,ã,å,æ,ą</string> + <!-- U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+011B: "ě" LATIN SMALL LETTER E WITH CARON --> + <string name="more_keys_for_e">ē,è,ė,é,ê,ë,ę,ě</string> + <!-- U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+0131: "ı" LATIN SMALL LETTER DOTLESS I --> + <string name="more_keys_for_i">ī,ì,į,í,î,ï,ı</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+0153: "œ" LATIN SMALL LIGATURE OE + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_o">ö,õ,ò,ó,ô,œ,ő,ø</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE --> + <string name="more_keys_for_u">ü,ū,ų,ù,ú,û,ů,ű</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA --> + <string name="more_keys_for_s">š,ß,ś,ş</string> + <!-- U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ņ,ñ,ń,ń</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ç,ć</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON --> + <string name="more_keys_for_d">ď</string> + <!-- U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + U+0159: "ř" LATIN SMALL LETTER R WITH CARON + U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE --> + <string name="more_keys_for_r">ŗ,ř,ŕ</string> + <!-- U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + U+0165: "ť" LATIN SMALL LETTER T WITH CARON --> + <string name="more_keys_for_t">ţ,ť</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE --> + <string name="more_keys_for_z">ž,ż,ź</string> + <!-- U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA --> + <string name="more_keys_for_k">ķ</string> + <!-- U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + U+013E: "ľ" LATIN SMALL LETTER L WITH CARON --> + <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string> + <!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE --> + <string name="more_keys_for_g">ģ,ğ</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row1_11">ü</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_11">ä</string> + <!-- U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE --> + <string name="more_keys_for_scandinavia_row2_10">õ</string> +</resources> diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml index 2c69c99d3..c8e98a1d8 100644 --- a/java/res/values-et/strings.xml +++ b/java/res/values-et/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Androidi klaviatuur"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-klaviatuur (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Androidi klaviatuuriseaded"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Sisestusvalikud"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Androidi parandus"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidi õigekirjakontroll"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidi õigekirjakontroll (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Õigekirjakontrolli seaded"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Kasuta lähedusandmeid"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Kasuta õigekirjakontrollis klaviatuurisarnast lähedusalgoritmi"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontakti nimede kontroll."</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Õigekirjakontroll kasutab teie kontaktisikute loendi sissekandeid"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreeri klahvivajutusel"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Heli klahvivajutusel"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Klahvivajutusel kuva hüpik"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Teksti parandamine"</string> <string name="misc_category" msgid="6894192814868233453">"Muud valikud"</string> <string name="advanced_settings" msgid="362895144495591463">"Täpsemad seaded"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Valikud ekspertkasutajatele"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Valikud ekspertidele"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Hüpiku loobumisviivitus"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Viivituseta"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Kuva alati"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Kuva portreerežiimis"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Peida alati"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Kuva seadete võti"</string> <string name="auto_correction" msgid="4979925752001319458">"Automaatparandus"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Tühik ja kirjavahemärgid parand. autom. kirjavigadega sõnad"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Väljas"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : salvestatud"</string> <string name="label_go_key" msgid="1635148082137219148">"Mine"</string> <string name="label_next_key" msgid="362972844525672568">"Edasi"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Eelm."</string> <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> <string name="label_send_key" msgid="2815056534433717444">"Saada"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Teksti ei ole sisestatud"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Klahvi kood: %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Tõstuklahv"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Tõstuklahv on lubatud"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Suurtähelukk on lubatud"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tõstuklahv sees (puudutage keelamiseks)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Suurtähelukk on sees (puudutage keelamiseks)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Kustuta"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Sümbolid"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Tähed"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Kõnesisend"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Naerunägu"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Tagasi"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vasaksulg"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paremsulg"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Koolon"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikoolon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Hüüumärk"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Küsimärk"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Jutumärgid"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Üksikjutumärgid"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Ruutjuur"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pii"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Kaubamärk"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Vahendaja"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Tärn"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Nael"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Kolmikpunkt"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alumised jutumärgid"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tõstuklahv on lubatud"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Suurtähelukk on lubatud"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tõstuklahv on keelatud"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Sümbolite režiim"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Tähtede režiim"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonirežiim"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefoni sümbolite režiim"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Kõnesisend"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Kõnesisendit ei toetata praegu teie keeles, kuid see töötab inglise keeles."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Kõnesisend kasutab Google\'i kõnetuvastust. Kehtivad "<a href="http://m.google.com/privacy">"Mobile\'i privaatsuseeskirjad"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Luba kasutaja tagasiside"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Saatke Google\'ile automaatselt kasutusstatistikat ja krahhiaruandeid ning aidake seda sisestusmeetodi redigeerijat parandada."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatuuri teema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Saksa QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inglise (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inglise (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kasutatavuse uurimisrežiim"</string> diff --git a/java/res/values-fa/donottranslate-more-keys.xml b/java/res/values-fa/donottranslate-more-keys.xml new file mode 100644 index 000000000..3e13c795a --- /dev/null +++ b/java/res/values-fa/donottranslate-more-keys.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+061F: "؟" ARABIC QUESTION MARK + U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064D: "ٍ" ARABIC KASRATAN + U+064B: "ً" ARABIC FATHATAN + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0655: "ٕ" ARABIC HAMZA BELOW + U+0654: "ٔ" ARABIC HAMZA ABOVE --> + <!-- U+064F: "ُ" ARABIC DAMMA + U+064C: "ٌ" ARABIC DAMMATAN + U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+0640: "ـ" ARABIC TATWEEL --> + <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',-,:,!,؟,،,؛,ِ,َ,ٍ,ً,ٖ,ٰ,ٕ,ٔ,ُ,ٌ,ّ,ْ,ٓ,ـــ|ـ,/"</string> + <string name="keyhintlabel_for_punctuation">ً</string> + <!-- U+0661: "١" ARABIC-INDIC DIGIT ONE --> + <string name="keylabel_for_symbols_1">١</string> + <!-- U+0662: "٢" ARABIC-INDIC DIGIT TWO --> + <string name="keylabel_for_symbols_2">٢</string> + <!-- U+0663: "٣" ARABIC-INDIC DIGIT THREE --> + <string name="keylabel_for_symbols_3">٣</string> + <!-- U+0664: "٤" ARABIC-INDIC DIGIT FOUR --> + <string name="keylabel_for_symbols_4">٤</string> + <!-- U+0665: "٥" ARABIC-INDIC DIGIT FIVE --> + <string name="keylabel_for_symbols_5">٥</string> + <!-- U+0666: "٦" ARABIC-INDIC DIGIT SIX --> + <string name="keylabel_for_symbols_6">٦</string> + <!-- U+0667: "٧" ARABIC-INDIC DIGIT SEVEN --> + <string name="keylabel_for_symbols_7">٧</string> + <!-- U+0668: "٨" ARABIC-INDIC DIGIT EIGHT --> + <string name="keylabel_for_symbols_8">٨</string> + <!-- U+0669: "٩" ARABIC-INDIC DIGIT NINE --> + <string name="keylabel_for_symbols_9">٩</string> + <!-- U+0660: "٠" ARABIC-INDIC DIGIT ZERO --> + <string name="keylabel_for_symbols_0">٠</string> + <string name="additional_more_keys_for_symbols_1">1</string> + <string name="additional_more_keys_for_symbols_2">2</string> + <string name="additional_more_keys_for_symbols_3">3</string> + <string name="additional_more_keys_for_symbols_4">4</string> + <string name="additional_more_keys_for_symbols_5">5</string> + <string name="additional_more_keys_for_symbols_6">6</string> + <string name="additional_more_keys_for_symbols_7">7</string> + <string name="additional_more_keys_for_symbols_8">8</string> + <string name="additional_more_keys_for_symbols_9">9</string> + <!-- U+066B: "٫" ARABIC DECIMAL SEPARATOR + U+066C: "٬" ARABIC THOUSANDS SEPARATOR --> + <string name="additional_more_keys_for_symbols_0">0,٫,٬</string> + <!-- U+060C: "،" ARABIC COMMA --> + <string name="keylabel_for_comma">،</string> + <string name="more_keys_for_comma">"\\,"</string> + <string name="keylabel_for_symbols_question">؟</string> + <string name="keylabel_for_symbols_semicolon">؛</string> + <!-- U+066A: "٪" ARABIC PERCENT SIGN --> + <string name="keylabel_for_symbols_percent">٪</string> + <string name="more_keys_for_symbols_question">\?</string> + <string name="more_keys_for_symbols_semicolon">;</string> + <!-- U+2030: "‰" PER MILLE SIGN --> + <string name="more_keys_for_symbols_percent">%,‰</string> + <!-- U+060C: "،" ARABIC COMMA + U+061B: "؛" ARABIC SEMICOLON + U+061F: "؟" ARABIC QUESTION MARK --> + <string name="keylabel_for_apostrophe">،</string> + <string name="keylabel_for_dash">"."</string> + <string name="keyhintlabel_for_apostrophe">؟</string> + <string name="keyhintlabel_for_dash">ً</string> + <string name="more_keys_for_apostrophe">"؟,؛,!,:,-,/,\',\""</string> + <!-- U+0651: "ّ" ARABIC SHADDA + U+0652: "ْ" ARABIC SUKUN + U+064C: "ٌ" ARABIC DAMMATAN + U+0653: "ٓ" ARABIC MADDAH ABOVE + U+064F: "ُ" ARABIC DAMMA --> + <!-- U+0650: "ِ" ARABIC KASRA + U+064E: "َ" ARABIC FATHA + U+064B: "ً" ARABIC FATHATAN + U+0640: "ـ" ARABIC TATWEEL + U+064D: "ٍ" ARABIC KASRATAN --> + <!-- U+0670: "ٰ" ARABIC LETTER SUPERSCRIPT ALEF + U+0656: "ٖ" ARABIC SUBSCRIPT ALEF + U+0654: "ٔ" ARABIC HAMZA ABOVE + U+0655: "ٕ" ARABIC HAMZA BELOW --> + <!-- In order to make Tatweel easily distinguishable from other punctuations, we use consecutive Tatweels only for its displayed label. --> + <string name="more_keys_for_dash">"ّ,ْ,ٌ,ٓ,ُ,ِ,َ,ً,ـــ|ـ,ٍ,ٔ,ٖ,ٕ,ٰ"</string> + <!-- U+266A: "♪" EIGHTH NOTE --> + <string name="more_keys_for_bullet">♪</string> + <!-- U+2605: "★" BLACK STAR + U+066D: "٭" ARABIC FIVE POINTED STAR --> + <string name="more_keys_for_star">★,٭</string> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- U+0029: ")" RIGHT PARENTHESIS --> + <integer name="keycode_for_left_parenthesis">0x0029</integer> + <!-- U+0028: "(" LEFT PARENTHESIS --> + <integer name="keycode_for_right_parenthesis">0x0028</integer> + <!-- U+FD3E: "﴾" ORNATE LEFT PARENTHESIS + U+FD3F: "﴿" ORNATE RIGHT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3E ORNATE LEFT PARENTHESIS --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FD3F ORNATE RIGHT PARENTHESIS --> + <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!4,﴾|﴿,<|>,{|},[|]</string> + <string name="more_keys_for_right_parenthesis">!fixedColumnOrder!4,﴿|﴾,>|<,}|{,]|[</string> + <!-- U+003E: ">" GREATER-THAN SIGN --> + <integer name="keycode_for_less_than">0x003E</integer> + <!-- U+003C: "<" LESS-THAN SIGN --> + <integer name="keycode_for_greater_than">0x003C</integer> + <!-- U+2264: "≤" LESS-THAN OR EQUAL TO + U+2265: "≥" GREATER-THAN EQUAL TO + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + The following characters don't need BIDI mirroring. + U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <string name="more_keys_for_less_than">!fixedColumnOrder!3,‹|›,≤|≥,«|»</string> + <string name="more_keys_for_greater_than">!fixedColumnOrder!3,›|‹,≥|≤,»|«</string> + <!-- U+005D: "]" RIGHT SQUARE BRACKET --> + <integer name="keycode_for_left_square_bracket">0x005D</integer> + <!-- U+005B: "[" LEFT SQUARE BRACKET --> + <integer name="keycode_for_right_square_bracket">0x005B</integer> + <!-- U+007D: "}" RIGHT CURLY BRACKET --> + <integer name="keycode_for_left_curly_bracket">0x007D</integer> + <!-- U+007B: "{" LEFT CURLY BRACKET --> + <integer name="keycode_for_right_curly_bracket">0x007B</integer> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«,‘,’,‚,‛</string> +</resources> diff --git a/java/res/values-fa/donottranslate.xml b/java/res/values-fa/donottranslate.xml new file mode 100644 index 000000000..57de2538b --- /dev/null +++ b/java/res/values-fa/donottranslate.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- Symbols that are suggested between words --> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> +</resources> diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml index 7d8c1e941..2696ed626 100644 --- a/java/res/values-fa/strings.xml +++ b/java/res/values-fa/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"صفحه کلید Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"صفحه کلید (Android (AOSP"</string> <string name="english_ime_settings" msgid="6661589557206947774">"تنظیمات صفحه کلید Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"گزینه های ورودی"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"تصحیح Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"غلطگیر املای Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"غلطگیر املای Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"تنظیمات غلط گیری املایی"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"استفاده از دادههای مجاورت"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"استفاده از یک الگوریتم مجاورت مشابه صفحه کلید برای غلط گیری املایی"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"جستجوی نام مخاطبین"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"غلطگیر املا از ورودیهای لیست مخاطبین شما استفاده میکند"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"لرزش با فشار کلید"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"صدا با فشار کلید"</string> <string name="popup_on_keypress" msgid="123894815723512944">"بازشدن با فشار کلید"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"تصحیح متن"</string> <string name="misc_category" msgid="6894192814868233453">"سایر گزینه ها"</string> <string name="advanced_settings" msgid="362895144495591463">"تنظیمات پیشرفته"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"گزینه هایی برای کاربران حرفه ای"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"گزینههایی برای حرفهایها"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"تغییر به دیگر روشهای ورودی"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"کلید تغییر زبان، سایر ورودیهای زبان را نیز پوشش میدهد"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"کلید تغییر زبان را فشار دهید"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"تأخیر در رد کردن کلید نمایشی"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"بدون تأخیر"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"پیش فرض"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"همیشه نمایش داده شود"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"نمایش در حالت عمودی"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"همیشه پنهان شود"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"نمایش کلید تنظیمات"</string> <string name="auto_correction" msgid="4979925752001319458">"تصحیح خودکار"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"کلید فاصله و علائم نگارشی به صورت خودکار کلماتی را که غلط تایپ شده اند تصحیح می کنند"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"خاموش"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : ذخیره شد"</string> <string name="label_go_key" msgid="1635148082137219148">"برو"</string> <string name="label_next_key" msgid="362972844525672568">"بعدی"</string> + <string name="label_previous_key" msgid="1211868118071386787">"قبلی"</string> <string name="label_done_key" msgid="2441578748772529288">"انجام شد"</string> <string name="label_send_key" msgid="2815056534433717444">"ارسال"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -80,8 +85,8 @@ <!-- no translation found for spoken_description_unknown (3197434010402179157) --> <skip /> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift فعال است"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock فعال شد"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift فعال است (برای غیرفعال کردن ضربه بزنید)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock روشن است (برای غیرفعال کردن ضربه بزنید)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"نمادها"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"حروف"</string> @@ -92,26 +97,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"ورودی صدا"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"صورت متبسم"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"کاما"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"نقطه"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"پرانتز چپ"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"پرانتز راست"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"دو نقطه"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"نقطه ویرگول"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"علامت تعجب"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"علامت سؤال"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"علامت نقل قول"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"علامت نقل قول تکی"</string> <string name="spoken_description_dot" msgid="40711082435231673">"نقطه"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"ریشه دوم"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"پی"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"دلتا"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"علامت تجاری"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"توسط"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"ستاره"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"پوند"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"سه نقطه"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"علامت نقل قول پایین"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift فعال است"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock فعال شد"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift غیرفعال است"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"حالت نمادها"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"حالت حروف"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"حالت تلفن"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"حالت نمادهای تلفن"</string> <string name="voice_warning_title" msgid="4419354150908395008">"ورودی صوتی"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ورودی صوتی در حال حاضر برای زبان شما پشتیبانی نمی شود اما برای زبان انگلیسی فعال است."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ورودی صوتی از تشخیص صدای Google استفاده می کند. "<a href="http://m.google.com/privacy">"خط مشی رازداری Mobile "</a>" اعمال می شود."</string> @@ -148,7 +141,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"فعال کردن بازخورد کاربر"</string> <string name="prefs_description_log" msgid="5827825607258246003">"با ارسال خودکار آمارهای کاربرد و گزارش های خرابی به Google، به بهبود این ویرایشگر روش ورودی کمک کنید."</string> <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه کلید"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY آلمانی"</string> <string name="subtype_en_GB" msgid="88170601942311355">"انگیسی (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"انگیسی (US)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"حالت بررسی قابلیت استفاده"</string> diff --git a/java/res/values-fi/donottranslate-more-keys.xml b/java/res/values-fi/donottranslate-more-keys.xml index df67c69ba..9b5fa786a 100644 --- a/java/res/values-fi/donottranslate-more-keys.xml +++ b/java/res/values-fi/donottranslate-more-keys.xml @@ -18,13 +18,39 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">æ,à,á,â,ã,ā</string> - <string name="more_keys_for_o">9,ø,ô,ò,ó,õ,œ,ō</string> - <string name="more_keys_for_u">7,ü</string> - <string name="more_keys_for_s">š,ß,ś</string> - <string name="more_keys_for_z">ž,ź,ż</string> - <string name="keylabel_for_scandinavia_row2_10">ö</string> - <string name="keylabel_for_scandinavia_row2_11">ä</string> - <string name="more_keys_for_scandinavia_row2_10">ø</string> - <string name="more_keys_for_scandinavia_row2_11">æ</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">æ,à,á,â,ã,ā</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ø,ô,ò,ó,õ,œ,ō</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS --> + <string name="more_keys_for_u">ü</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE --> + <string name="more_keys_for_s">š,ß,ś</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE --> + <string name="more_keys_for_z">ž,ź,ż</string> + <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE --> + <string name="keylabel_for_scandinavia_row1_11">å</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_11">ä</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_scandinavia_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="more_keys_for_scandinavia_row2_11">æ</string> </resources> diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml index c77cd8107..ecb7a4d02 100644 --- a/java/res/values-fi/strings.xml +++ b/java/res/values-fi/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-näppäimistö"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-näppäimistö (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android-näppäimistön asetukset"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Syöttövalinnat"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korjaus"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-oikoluku"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-oikoluku (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Oikoluvun asetukset"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Käytä lähestymistietoja"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Käytä näppäimistön kaltaista lähestymisalgoritmia oikolukuun"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Hae kontaktien nimiä"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Oikeinkirjoituksen tarkistus käyttää kontaktiluettelosi tietoja."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Toista ääni näppäimiä painettaessa"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Ponnahdusikkuna painalluksella"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Tekstin korjaus"</string> <string name="misc_category" msgid="6894192814868233453">"Muut vaihtoehdot"</string> <string name="advanced_settings" msgid="362895144495591463">"Lisäasetukset"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Valinnat kokeneille käyttäjille"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Valinnat asiantuntijoille"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Näppäimen hylkäysviive"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ei viivettä"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Näytä aina"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Näytä pystysuunnassa"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Piilota aina"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Näytä asetukset-näppäin"</string> <string name="auto_correction" msgid="4979925752001319458">"Autom. korjaus"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Välilyönnit ja välimerkit korjaavat väärinkirjoitetut sanat automaattisesti"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Älä käytä"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Tallennettu"</string> <string name="label_go_key" msgid="1635148082137219148">"Siirry"</string> <string name="label_next_key" msgid="362972844525672568">"Seur."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Edell"</string> <string name="label_done_key" msgid="2441578748772529288">"Valmis"</string> <string name="label_send_key" msgid="2815056534433717444">"Lähetä"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Ei kirjoitettua tekstiä"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Näppäimen koodi %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift päällä"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock päällä"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Vaihto päällä (napauta poistaaksesi käytöstä)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock päällä (napauta poistaaksesi käytöstä)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Poisto"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbolit"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Kirjaimet"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Puheohjaus"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Hymiö"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Pilkku"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Piste"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vasen sulkumerkki"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Oikea sulkumerkki"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kaksoispiste"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Puolipiste"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Huutomerkki"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Kysymysmerkki"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Lainausmerkki"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Puolilainausmerkki"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Piste"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Neliöjuuri"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pii"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Tavaramerkki"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"C/O"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Tähti"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Punta"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsi"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Rivinalinen lainausmerkki"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Vaihto päällä"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock päällä"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Vaihto pois käytöstä"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolit-tila"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Näppäimistötila"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Puhelintila"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Puhelinsymbolit-tila"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Äänisyöte"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Äänisyötettä ei vielä tueta kielelläsi, mutta voit käyttää sitä englanniksi."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Äänisyöte käyttää Googlen puheentunnistusta. "<a href="http://m.google.com/privacy">"Mobile-tietosuojakäytäntö"</a>" on voimassa."</string> @@ -123,7 +119,7 @@ <string name="voice_server_error" msgid="7807129913977261644">"Palvelinvirhe"</string> <string name="voice_speech_timeout" msgid="8461817525075498795">"Puhetta ei kuulu"</string> <string name="voice_no_match" msgid="4285117547030179174">"Ei vastineita"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Äänihakua ei asennettu"</string> + <string name="voice_not_installed" msgid="5552450909753842415">"Puhehakua ei asennettu"</string> <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Vihje:"</b>" liu\'uta sormea näppäimistöllä ja puhu"</string> <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Vihje:"</b>" kokeile seuraavalla kerralla puhua välimerkit, kuten \"period\" (piste), \"comma\" (pilkku) tai \"question mark\" (kysymysmerkki)."</string> <string name="cancel" msgid="6830980399865683324">"Peruuta"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Ota käyttäjäpalaute käyttöön"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Auta parantamaan tätä syöttötavan muokkausohjelmaa lähettämällä automaattisesti käyttötietoja ja kaatumisraportteja Googlelle."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Näppäimistöteema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"saksa, QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"englanti (Iso-Britannia)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"englanti (Yhdysvallat)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Käytettävyystutkimustila"</string> diff --git a/java/res/values-fr/donottranslate-more-keys.xml b/java/res/values-fr/donottranslate-more-keys.xml index cd6d49bad..7b11a183d 100644 --- a/java/res/values-fr/donottranslate-more-keys.xml +++ b/java/res/values-fr/donottranslate-more-keys.xml @@ -18,14 +18,51 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,â,1,æ,á,ä,ã,å,ā,ª</string> - <string name="more_keys_for_e">é,è,ê,ë,3,ę,ė,ē</string> - <string name="more_keys_for_i">î,8,ï,ì,í,į,ī</string> - <string name="more_keys_for_o">ô,œ,9,ö,ò,ó,õ,ø,ō,º</string> - <string name="more_keys_for_u">ù,û,7,ü,ú,ū</string> - <string name="more_keys_for_c">ç,ć,č</string> - <string name="more_keys_for_y">6,ÿ</string> - <string name="more_keys_for_q"></string> - <string name="more_keys_for_w"></string> - <string name="more_keys_for_z">2</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00AA: "ª" FEMININE ORDINAL INDICATOR --> + <string name="more_keys_for_a">à,â,%,æ,á,ä,ã,å,ā,ª</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,è,ê,ë,%,ę,ė,ē</string> + <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">î,%,ï,ì,í,į,ī</string> + <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00BA: "º" MASCULINE ORDINAL INDICATOR --> + <string name="more_keys_for_o">ô,œ,%,ö,ò,ó,õ,ø,ō,º</string> + <!-- U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ù,û,%,ü,ú,ū</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ç,ć,č</string> + <!-- U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">%,ÿ</string> </resources> diff --git a/java/res/values-fr/donottranslate.xml b/java/res/values-fr/donottranslate.xml index 695750f32..8cf2516a6 100644 --- a/java/res/values-fr/donottranslate.xml +++ b/java/res/values-fr/donottranslate.xml @@ -19,11 +19,11 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Symbols that should be swapped with a magic space --> - <string name="magic_space_swapping_symbols">.,\u0022)]}</string> + <string name="weak_space_swapping_symbols">.,\")]}</string> <!-- Symbols that should strip a magic space --> - <string name="magic_space_stripping_symbols">\u0009\u0020\u0027\n-/_</string> + <string name="weak_space_stripping_symbols">"	 \'\n-/_"</string> <!-- Symbols that should promote magic spaces into real space --> - <string name="magic_space_promoting_symbols">;:!?([*&@{<>+=|</string> + <string name="phantom_space_promoting_symbols">;:!?([*&@{<>+=|</string> <!-- Symbols that do NOT separate words --> - <string name="symbols_excluded_from_word_separators">\u0027</string> + <string name="symbols_excluded_from_word_separators">\'</string> </resources> diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 7b89edd54..3a5f6a1b3 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Clavier Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Clavier Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Paramètres du clavier Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Options de saisie"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Correcteur Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Correcteur orthographique Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Correcteur orthographique Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Paramètre du correcteur orthographique"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Utiliser données proximité"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utiliser algorithme de proximité clavier pour correcteur ortho"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Rechercher noms contacts"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Correcteur orthographique utilise entrées de liste de contacts."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Son à chaque touche"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Agrandir les caractères"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Correction du texte"</string> <string name="misc_category" msgid="6894192814868233453">"Autres options"</string> <string name="advanced_settings" msgid="362895144495591463">"Paramètres avancés"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Options destinées aux utilisateurs expérimentés"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Options destinées aux experts"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sans délai"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Toujours afficher"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Afficher en mode Portrait"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Toujours masquer"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Afficher touche param."</string> <string name="auto_correction" msgid="4979925752001319458">"Correction automatique"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Corriger autom. orthographe (pression sur barre espace/signes ponctuation)"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Désactiver"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : enregistré"</string> <string name="label_go_key" msgid="1635148082137219148">"OK"</string> <string name="label_next_key" msgid="362972844525672568">"Suiv."</string> + <string name="label_previous_key" msgid="1211868118071386787">"Préc."</string> <string name="label_done_key" msgid="2441578748772529288">"OK"</string> <string name="label_send_key" msgid="2815056534433717444">"Envoi"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Aucun texte saisi"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Code touche %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Maj"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Touche Maj activée"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Verrouillage des majuscules activé"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Touche Maj activée (appuyer pour désactiver)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Verrouillage des majuscules activé (appuyer pour désactiver)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Supprimer"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboles"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Lettres"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Saisie vocale"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Émoticône"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Entrée"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Virgule"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Point"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parenthèse gauche"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parenthèse droite"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Deux-points"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Point-virgule"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Point d\'exclamation"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Point d\'interrogation"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Guillemets doubles"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Apostrophe"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Point"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Racine carrée"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marque commerciale"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"à l\'attention de"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Étoile"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Dièse"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Guillemets bas doubles"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Touche Maj activée"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Verrouillage des majuscules activé"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Touche Maj désactivée"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode Symboles"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode Lettres"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode Téléphone"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode Symboles du téléphone"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Saisie vocale"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"La saisie vocale n\'est pas encore prise en charge pour votre langue, mais elle fonctionne en anglais."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"La saisie vocale fait appel à la reconnaissance vocale de Google. Les "<a href="http://m.google.com/privacy">"Règles de confidentialité Google Mobile"</a>" s\'appliquent."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Autoriser les commentaires des utilisateurs"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Contribuer à l\'amélioration de cet éditeur du mode de saisie grâce à l\'envoi automatique de statistiques d\'utilisation et de rapports d\'incident à Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Clavier QWERTY allemand"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (Royaume-Uni)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mode d\'étude de l\'utilisabilité"</string> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index de95ab8d7..c20e50ff0 100644 --- a/java/res/values-hi/strings.xml +++ b/java/res/values-hi/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android कीबोर्ड"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android कीबोर्ड (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android कीबोर्ड सेटिंग"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"इनपुट विकल्प"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android correction"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android वर्तनी परीक्षक"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android वर्तनी परीक्षक (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"वर्तनी जांच सेटिंग"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"निकटस्थ डेटा उपयोग करें"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"वर्तनी जांचने के लिए कीबोर्ड जैसे निकटस्थ एल्गोरिदम का उपयोग करें"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"संपर्क नामों को खोजें"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"वर्तनी परीक्षक आपकी संपर्क सूची की प्रविष्टियों का उपयोग करता है"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"कुंजी दबाने पर कंपन करता है"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"कुंजी दबाने पर आवाज"</string> <string name="popup_on_keypress" msgid="123894815723512944">"कुंजी दबाने पर पॉपअप दिखाएं"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"पाठ सुधार"</string> <string name="misc_category" msgid="6894192814868233453">"अन्य विकल्प"</string> <string name="advanced_settings" msgid="362895144495591463">"उन्नत सेटिंग"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"विशेषज्ञ उपयोगकर्ताओं के लिए विकल्प"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"विशेषज्ञों के लिए विकल्प"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"कुंजी पॉपअप खारिज़ विलंब"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"कोई विलंब नहीं"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"डिफ़ॉल्ट"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"हमेशा दिखाएं"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"र्पोट्रेट मोड पर प्रदर्शित करें"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"हमेशा छुपाएं"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"सेटिंग कुंजी प्रदर्शित करता है"</string> <string name="auto_correction" msgid="4979925752001319458">"स्वत: सुधार"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Spacebar और विराम चिह्न गलत लिखे गए शब्दों को स्वचालित रूप से ठीक करते हैं"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"बंद"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: सहेजा गया"</string> <string name="label_go_key" msgid="1635148082137219148">"जाएं"</string> <string name="label_next_key" msgid="362972844525672568">"अगला"</string> + <string name="label_previous_key" msgid="1211868118071386787">"पिछला"</string> <string name="label_done_key" msgid="2441578748772529288">"पूर्ण"</string> <string name="label_send_key" msgid="2815056534433717444">"भेजें"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"कोई पाठ दर्ज नहीं किया गया"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"कुंजी कोड %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"शिफ़्ट"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"शिफ़्ट सक्षम किया गया है"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"कैप्स लॉक सक्षम किया गया है"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift चालू (अक्षम करने के लिए टैप करें)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock चालू (अक्षम करने के लिए टैप करें)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"डिलीट"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"प्रतीक"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"अक्षर"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"ध्वनि इनपुट"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"मुस्कुराता चेहरा"</string> <string name="spoken_description_return" msgid="8178083177238315647">"रिटर्न"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"अल्पविराम"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"पूर्णविराम"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"बायां कोष्ठक"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"दायां कोष्ठक"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"अपूर्ण विराम"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"अर्द्धविराम"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"विस्मयादिबोधक चिह्न"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"प्रश्नचिह्न"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"दोहरा उद्धरण"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"एकल उद्धरण"</string> <string name="spoken_description_dot" msgid="40711082435231673">"बिंदु"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"वर्गमूल"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"पाइ"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"डेल्टा"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"ट्रेडमार्क"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"संरक्षक"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"तारा"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"पाउंड"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"पदलोप चिह्न"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"निम्न दोहरा उद्धरण"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift सक्षम किया गया"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock सक्षम किया गया"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift अक्षम किया गया"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"प्रतीक मोड"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"अक्षर मोड"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"फ़ोन मोड"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"फ़ोन प्रतीक मोड"</string> <string name="voice_warning_title" msgid="4419354150908395008">"ध्वनि इनपुट"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ध्वनि इनपुट आपकी भाषा के लिए अभी समर्थित नहीं है, पर अंग्रेज़ी में कार्य करता है."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ध्वनि इनपुट Google की वाक् पहचान का उपयोग करता है. "<a href="http://m.google.com/privacy">"मोबाइल गोपनीयता नीति"</a>" लागू होती है."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"उपयोगकर्ता फ़ीडबैक सक्षम करें"</string> <string name="prefs_description_log" msgid="5827825607258246003">"उपयोग के आंकड़े और क्रैश रिपोर्ट Google को स्वचालित रूप से भेज कर इस इनपुट पद्धति संपादक को बेहतर बनाने में सहायता करें."</string> <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"जर्मन QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेज़ी (यूके)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेज़ी (यूएस)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"उपयोगिता अध्ययन मोड"</string> diff --git a/java/res/values-hr/donottranslate-more-keys.xml b/java/res/values-hr/donottranslate-more-keys.xml index c34e0e646..9b4005d0d 100644 --- a/java/res/values-hr/donottranslate-more-keys.xml +++ b/java/res/values-hr/donottranslate-more-keys.xml @@ -18,10 +18,21 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_s">š,ś,ß</string> - <string name="more_keys_for_n">ñ,ń</string> - <string name="more_keys_for_y"></string> - <string name="more_keys_for_z">6,ž,ź,ż</string> - <string name="more_keys_for_c">č,ć,ç</string> - <string name="more_keys_for_d">đ</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+00DF: "ß" LATIN SMALL LETTER SHARP S --> + <string name="more_keys_for_s">š,ś,ß</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE --> + <string name="more_keys_for_z">ž,ź,ż</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA --> + <string name="more_keys_for_c">č,ć,ç</string> + <!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE --> + <string name="more_keys_for_d">đ</string> </resources> diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml index 30c20b3cc..ef491f43a 100644 --- a/java/res/values-hr/strings.xml +++ b/java/res/values-hr/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android tipkovnica"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tipkovnica (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Postavke tipkovnice za Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opcije ulaza"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Ispravak za Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidova provjera pravopisa"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidova provjera pravopisa (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Postavke provjere pravopisa"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Upotreba podataka blizine"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Za prov. pravopisa upotrijebi algoritam blizine kao na tipkovnici"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Potražite imena kontakata"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Provjera pravopisa upotrebljava unose iz vašeg popisa kontakata"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri pritisku tipke"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Povećanja na pritisak tipke"</string> @@ -34,8 +36,14 @@ <string name="correction_category" msgid="2236750915056607613">"Ispravak teksta"</string> <string name="misc_category" msgid="6894192814868233453">"Ostale opcije"</string> <string name="advanced_settings" msgid="362895144495591463">"Napredne postavke"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcije za stručne korisnike"</string> - <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Bez odgode klj. skočnih"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcije za stručnjake"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> + <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Odgoda prikaza tipki"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez odgode"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string> <string name="use_contacts_dict" msgid="4435317977804180815">"Predlaži imena kontakata"</string> @@ -50,9 +58,8 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Uvijek prikaži"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Prikaži u portretnom načinu"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Uvijek sakrij"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Prikaži tipku postavki"</string> <string name="auto_correction" msgid="4979925752001319458">"Samoispravak"</string> - <string name="auto_correction_summary" msgid="5625751551134658006">"Razm. i intrp. aut. ispr. kr. rči."</string> + <string name="auto_correction_summary" msgid="5625751551134658006">"Razmak i interpunkcija automatski ispravljaju krive riječi"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Isključeno"</string> <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Skromno"</string> <string name="auto_correction_threshold_mode_aggeressive" msgid="3524029103734923819">"Agresivno"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Spremljeno"</string> <string name="label_go_key" msgid="1635148082137219148">"Idi"</string> <string name="label_next_key" msgid="362972844525672568">"Dalje"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Pret."</string> <string name="label_done_key" msgid="2441578748772529288">"Gotovo"</string> <string name="label_send_key" msgid="2815056534433717444">"Pošalji"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nije unesen tekst"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kôd tipke %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift je omogućen"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock omogućen"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Uključena tipka Shift (dotaknite da onemogućite)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Uključeno je pisanje velikim slovima (Caps Lock) (dotaknite da onemogućite)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Slova"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Glasovni unos"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smješko"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Zarez"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Točka"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Lijeva zagrada"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Desna zagrada"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dvotočka"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Točka-zarez"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uskličnik"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Upitnik"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvostruki navodnici"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Jednostruki navodnici"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Točka"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratni korijen"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Zaštitni znak"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"U ruke"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Zvjezdica"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"funta"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri točke"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Donji dvostruki navodnici"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Omogućena tipka Shift"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Omogućeno pisanje velikih slova"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Onemogućena tipka Shift"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Način unosa simbola"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Način pisanja slova"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonski način rada"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Način unosa telefonskih simbola"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Glasovni ulaz"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Vaš jezik trenutno nije podržan za glasovni unos, ali radi za engleski."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Glasovni unos upotrebljava Googleovo prepoznavanje govora. Primjenjuju se "<a href="http://m.google.com/privacy">"Pravila o privatnosti za uslugu Mobile"</a>"."</string> @@ -132,7 +128,7 @@ <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavnoj tipkovnici"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipkovnici simb."</string> <string name="voice_input_modes_off" msgid="3745699748218082014">"Isključeno"</string> - <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. na gl. tipk."</string> + <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na gl. tipkovnici"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. simb."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. unos onemog."</string> <string name="selectInputMethod" msgid="315076553378705821">"Odabir ulazne metode"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Omogući korisničke povratne informacije"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Pomozite u poboljšanju ovog urednika ulazne metode automatskim slanjem statistike upotrebe i padova Googleu."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"njemački QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engleski (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engleski (SAD)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način studije upotrebljivosti"</string> diff --git a/java/res/values-hu/donottranslate-more-keys.xml b/java/res/values-hu/donottranslate-more-keys.xml index 42b330199..48259104b 100644 --- a/java/res/values-hu/donottranslate-more-keys.xml +++ b/java/res/values-hu/donottranslate-more-keys.xml @@ -18,11 +18,45 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,à,â,ä,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,é,è,ê,ë,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,î,ï,ì,į,ī</string> - <string name="more_keys_for_o">9,ó,ö,ő,ô,ò,õ,œ,ø,ō</string> - <string name="more_keys_for_u">7,ú,ü,ű,û,ù,ū</string> - <string name="more_keys_for_y"></string> - <string name="more_keys_for_z">6</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">á,à,â,ä,æ,ã,å,ā</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,è,ê,ë,ę,ė,ē</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,î,ï,ì,į,ī</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ó,ö,ő,ô,ò,õ,œ,ø,ō</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,ű,û,ù,ū</string> </resources> diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml index 180b6fcf9..4ac6bf3c2 100644 --- a/java/res/values-hu/strings.xml +++ b/java/res/values-hu/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-billentyűzet"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-billentyűzet (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android billentyűzetbeállítások"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Beviteli beállítások"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android korrekció"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidos helyesírás-ellenőrző"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidos helyesírás-ellenőrző (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Helyesírás-ellenőrzés beállításai"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Közelségi adatok haszn."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Billentyűzetszerű algoritmus a helyesírás-ellenőrzéshez"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Névjegyek keresése"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"A helyesírás-ellenőrző használja a névjegyek bejegyzéseit"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés billentyű megnyomása esetén"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés billentyű megnyomása esetén"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Legyen nagyobb billentyű lenyomásakor"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Szövegjavítás"</string> <string name="misc_category" msgid="6894192814868233453">"Egyéb beállítások"</string> <string name="advanced_settings" msgid="362895144495591463">"Speciális beállítások"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Beállítások gyakorlott felhasználóknak"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Beállítások gyakorlott felhasználóknak"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Gombeltüntetés késése"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nincs késés"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Alapbeállítás"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mindig látszik"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Megjelenítés álló tájolásban"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Mindig rejtve"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Beállítások billentyű megjelenítése"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatikus javítás"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Szóköz és központozás automatikusan javítja az elgépelést"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Ki"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : mentve"</string> <string name="label_go_key" msgid="1635148082137219148">"Ugrás"</string> <string name="label_next_key" msgid="362972844525672568">"Tovább"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Előző"</string> <string name="label_done_key" msgid="2441578748772529288">"Kész"</string> <string name="label_send_key" msgid="2815056534433717444">"Küldés"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Szöveg nincs megadva"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Billentyűkód: %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift engedélyezve"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock bekapcsolva"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift be van kapcsolva (érintse meg a kikapcsoláshoz)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock be van kapcsolva (érintse meg a kikapcsoláshoz)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Törlés"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Szimbólumok"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Betűk"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Hangbevitel"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Mosolygós arc"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Vessző"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Pont"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Nyitó zárójel"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Berekesztő zárójel"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kettőspont"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Pontosvessző"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Felkiáltójel"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Kérdőjel"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dupla idézőjel"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Szimpla idézőjel"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Pont"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Négyzetgyök"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Védjegy"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Százalék"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Csillag"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Kettős kereszt"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Kihagyás"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alsó dupla idézőjel"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift bekapcsolva"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock bekapcsolva"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift kikapcsolva"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"\"Szimbólumok\" mód"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"\"Betű\" mód"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"\"Telefon\" mód"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"\"Telefonos szimbólumok\" mód"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Hangbevitel"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"A hangbevitel szolgáltatás jelenleg nem támogatja az Ön nyelvét, ám angolul működik."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A hangbevitel a Google beszédfelismerő technológiáját használja, amelyre a "<a href="http://m.google.com/privacy">"Mobil adatvédelmi irányelvek"</a>" érvényesek."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Felhasználói visszajelzés engedélyezése"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Segíthet ennek a beviteli módszernek a javításában, ha engedélyezi a használati statisztikák és a hibajelentések elküldését a Google-nak."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Billentyűzettéma"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Német QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"angol (brit)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"angol (amerikai)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Használhatósági teszt"</string> diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml index a023b6477..f10d613f2 100644 --- a/java/res/values-in/strings.xml +++ b/java/res/values-in/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Keyboard Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Keyboard Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Setelan keyboard Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opsi masukan"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Koreksi android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Pemeriksa ejaan Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pemeriksa ejaan Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Setelan pemeriksaan ejaan"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Gunakan data kedekatan"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gunakan algoritme kedekatan seperti keyboard untuk memeriksa ejaan"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pemeriksa ejaan menggunakan entri dari daftar kenalan Anda"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Berbunyi jika tombol ditekan"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Muncul saat tombol ditekan"</string> @@ -34,10 +36,16 @@ <string name="correction_category" msgid="2236750915056607613">"Koreksi teks"</string> <string name="misc_category" msgid="6894192814868233453">"Opsi lain"</string> <string name="advanced_settings" msgid="362895144495591463">"Setelan lanjutan"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Pilihan untuk pengguna ahli"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opsi untuk ahli"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string> - <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Bawaan"</string> + <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string> <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kenalan"</string> <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kenalan untuk saran dan koreksi"</string> <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Selalu tampilkan"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Tampilkan pada mode potret"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Selalu sembunyikan"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Lihat tombol setelan"</string> <string name="auto_correction" msgid="4979925752001319458">"Koreksi otomatis"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Bilah spasi dan tanda baca secara otomatis dikoreksi pada kata yang salah ketik"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Mati"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Telah disimpan"</string> <string name="label_go_key" msgid="1635148082137219148">"Buka"</string> <string name="label_next_key" msgid="362972844525672568">"Berikutnya"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> <string name="label_send_key" msgid="2815056534433717444">"Kirimkan"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Tidak ada teks yang dimasukkan"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kode tombol %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift diaktifkan"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock diaktifkan"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aktif (ketuk untuk menonaktifkan)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock aktif (ketuk untuk menonaktifkan)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Hapus"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbol"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Huruf"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Masukan suara"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Wajah tersenyum"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Kembali"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Titik"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kurung tutup"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Kurung buka"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Titik Dua"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Titik koma"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tanda seru"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tanda tanya"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Tanda petik"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Petik tunggal"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Akar pangkat dua"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Merek dagang"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Dengan alamat"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Bintang"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pon"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Tanda petik bawah"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift diaktifkan"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock diaktifkan"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift dinonaktifkan"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode simbol"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode huruf"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode telepon"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode simbol telepon"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Masukan suara"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Masukan suara saat ini tidak didukung untuk bahasa Anda, tetapi bekerja dalam Bahasa Inggris."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Masukan suara menggunakan pengenalan ucapan Google. "<a href="http://m.google.com/privacy">"Kebijakan Privasi Seluler"</a>" berlaku."</string> @@ -141,10 +137,9 @@ <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string> <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Sentuh sekali lagi untuk menyimpan"</string> <string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string> - <string name="prefs_enable_log" msgid="6620424505072963557">"Aktifkan umpan balik pengguna"</string> + <string name="prefs_enable_log" msgid="6620424505072963557">"Aktifkan masukan pengguna"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Bantu tingkatkan metode editor masukan dengan mengirim statistik penggunaan dan laporan kerusakan ke Google secara otomatis."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema keyboard"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY Jerman"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inggris (Inggris)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inggris (AS)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus studi daya guna"</string> diff --git a/java/res/values-it/donottranslate-more-keys.xml b/java/res/values-it/donottranslate-more-keys.xml index fa1537bec..17dd03108 100644 --- a/java/res/values-it/donottranslate-more-keys.xml +++ b/java/res/values-it/donottranslate-more-keys.xml @@ -18,9 +18,45 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,á,â,ä,æ,ã,å,ā,ª</string> - <string name="more_keys_for_e">3,è,é,ê,ë,ę,ė,ē</string> - <string name="more_keys_for_i">8,ì,í,î,ï,į,ī</string> - <string name="more_keys_for_o">9,ò,ó,ô,ö,õ,œ,ø,ō,º</string> - <string name="more_keys_for_u">7,ù,ú,û,ü,ū</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00AA: "ª" FEMININE ORDINAL INDICATOR --> + <string name="more_keys_for_a">à,á,â,ä,æ,ã,å,ā,ª</string> + <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">è,é,ê,ë,ę,ė,ē</string> + <!-- U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">ì,í,î,ï,į,ī</string> + <!-- U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00BA: "º" MASCULINE ORDINAL INDICATOR --> + <string name="more_keys_for_o">ò,ó,ô,ö,õ,œ,ø,ō,º</string> + <!-- U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ù,ú,û,ü,ū</string> </resources> diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 58c0e2c3b..d65a568c0 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Tastiera Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastiera Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Impostazioni tastiera Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opzioni inserimento"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Correzione Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Controllo ortografico Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Controllo ortografico Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Impostazioni di controllo ortografico"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Usa i dati di prossimità"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usa algoritmo prossimità (come in tastiere) per controllo ortografico"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cerca in nomi contatti"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"La funzione di controllo ortografico usa voci dell\'elenco contatti"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Suono tasti"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Popup sui tasti"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Correzione testo"</string> <string name="misc_category" msgid="6894192814868233453">"Altre opzioni"</string> <string name="advanced_settings" msgid="362895144495591463">"Impostazioni avanzate"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opzioni per utenti esperti"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opzioni per esperti"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ritardo eliminaz. popup tasto"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nessun ritardo"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostra in modalità verticale"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nascondi sempre"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostra tasto impostazioni"</string> <string name="auto_correction" msgid="4979925752001319458">"Correzione automatica"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Barra spaziatrice/punteggiatura correggono parole con errori"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : parola salvata"</string> <string name="label_go_key" msgid="1635148082137219148">"Vai"</string> <string name="label_next_key" msgid="362972844525672568">"Avanti"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Indietro"</string> <string name="label_done_key" msgid="2441578748772529288">"Fine"</string> <string name="label_send_key" msgid="2815056534433717444">"Invia"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nessun testo inserito"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Codice tasto %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Maiuscolo"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Maiuscolo attivo"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Blocco maiuscole attivo"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Maiuscolo attivo (tocca per disattivare)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Blocco maiuscole attivo (tocca per disattivare)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Cancella"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Lettere"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Input vocale"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smile"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Invio"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Virgola"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punto"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parentesi aperta"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parentesi chiusa"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Due punti"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Punto e virgola"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Punto esclamativo"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Punto interrogativo"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Virgolette doppie"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Virgolette semplici"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Pallino"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Radice quadrata"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi greco"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marchio commerciale"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Presso"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Cancelletto"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellissi"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Virgolette doppie basse"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Maiuscolo attivo"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Blocco maiuscole attivo"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Maiuscolo disattivato"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modalità simboli"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modalità lettere"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modalità telefono"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modalità simboli telefono"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Comandi vocali"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"I comandi vocali non sono attualmente supportati per la tua lingua ma funzionano in inglese."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"L\'input vocale utilizza il riconoscimento vocale di Google. Sono valide le "<a href="http://m.google.com/privacy">"norme sulla privacy di Google Mobile"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Attiva commenti degli utenti"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Aiuta a migliorare l\'editor del metodo di inserimento inviando automaticamente a Google statistiche sull\'utilizzo e segnalazioni sugli arresti anomali."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema della tastiera"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY tedesca"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inglese (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inglese (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modalità Studio sull\'usabilità"</string> diff --git a/java/res/values-iw/donottranslate-more-keys.xml b/java/res/values-iw/donottranslate-more-keys.xml index 829486f7b..c5431b612 100644 --- a/java/res/values-iw/donottranslate-more-keys.xml +++ b/java/res/values-iw/donottranslate-more-keys.xml @@ -18,6 +18,52 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_star">★</string> - <string name="more_keys_for_plus">±,﬩</string> + <!-- U+2605: "★" BLACK STAR --> + <string name="more_keys_for_star">★</string> + <!-- U+00B1: "±" PLUS-MINUS SIGN + U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN --> + <string name="more_keys_for_plus">±,﬩</string> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- U+0029: ")" RIGHT PARENTHESIS --> + <integer name="keycode_for_left_parenthesis">0x0029</integer> + <!-- U+0028: "(" LEFT PARENTHESIS --> + <integer name="keycode_for_right_parenthesis">0x0028</integer> + <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!3,<|>,{|},[|]</string> + <string name="more_keys_for_right_parenthesis">!fixedColumnOrder!3,>|<,}|{,]|[</string> + <!-- U+003E: ">" GREATER-THAN SIGN --> + <integer name="keycode_for_less_than">0x003E</integer> + <!-- U+003C: "<" LESS-THAN SIGN --> + <integer name="keycode_for_greater_than">0x003C</integer> + <!-- U+2264: "≤" LESS-THAN OR EQUAL TO + U+2265: "≥" GREATER-THAN EQUAL TO + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + The following characters don't need BIDI mirroring. + U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <string name="more_keys_for_less_than">!fixedColumnOrder!3,‹|›,≤|≥,«|»</string> + <string name="more_keys_for_greater_than">!fixedColumnOrder!3,›|‹,≥|≤,»|«</string> + <!-- U+005D: "]" RIGHT SQUARE BRACKET --> + <integer name="keycode_for_left_square_bracket">0x005D</integer> + <!-- U+005B: "[" LEFT SQUARE BRACKET --> + <integer name="keycode_for_right_square_bracket">0x005B</integer> + <!-- U+007D: "}" RIGHT CURLY BRACKET --> + <integer name="keycode_for_left_curly_bracket">0x007D</integer> + <!-- U+007B: "{" LEFT CURLY BRACKET --> + <integer name="keycode_for_right_curly_bracket">0x007B</integer> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_double_quote">“,”,„,‟,«|»,»|«</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«|»,»|«;,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,“,”,«|»,»|«,‘,’,‚,‛</string> </resources> diff --git a/java/res/values-iw/donottranslate.xml b/java/res/values-iw/donottranslate.xml new file mode 100644 index 000000000..57de2538b --- /dev/null +++ b/java/res/values-iw/donottranslate.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- Symbols that are suggested between words --> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(|),)|(,\',-,/,@,_</string> +</resources> diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml index 292517c68..dabbd4d05 100644 --- a/java/res/values-iw/strings.xml +++ b/java/res/values-iw/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"מקלדת Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"מקלדת Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"הגדרות מקלדת של Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"אפשרויות קלט"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"תיקון Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"בודק האיות של Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"בודק האיות של Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"הגדרות בדיקת איות"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"שימוש בנתוני הקירבה"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"השתמש באלגוריתם קירבה דמוי-מקלדת עבור בדיקת איות"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"חפש שמות של אנשי קשר"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"בודק האיות משתמש בערכים מרשימת אנשי הקשר שלך"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"רטט בלחיצה על מקשים"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"צלילים בעת לחיצה על מקשים"</string> <string name="popup_on_keypress" msgid="123894815723512944">"חלון קופץ בלחיצה על מקש"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"תיקון טקסט"</string> <string name="misc_category" msgid="6894192814868233453">"אפשרויות אחרות"</string> <string name="advanced_settings" msgid="362895144495591463">"הגדרות מתקדמות"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"אפשרויות עבור משתמשים מתקדמים"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"אפשרויות למומחים"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"עבור לשיטות קלט אחרות"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"מתג החלפת השפה מכסה גם שיטות קלט אחרות"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"הסתר את מתג החלפת השפה"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"עיכוב סגירת חלון קופץ של מקש"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ללא עיכוב"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ברירת מחדל"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"הצג תמיד"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"הצג בפריסה לאורך"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"הסתר תמיד"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"הצג מקש הגדרות"</string> <string name="auto_correction" msgid="4979925752001319458">"תיקון אוטומטי"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"מקש הרווח ופיסוק מתקנים אוטומטית שגיאות הקלדה"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"כבוי"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : נשמרה"</string> <string name="label_go_key" msgid="1635148082137219148">"בצע"</string> <string name="label_next_key" msgid="362972844525672568">"הבא"</string> + <string name="label_previous_key" msgid="1211868118071386787">"הקודם"</string> <string name="label_done_key" msgid="2441578748772529288">"סיום"</string> <string name="label_send_key" msgid="2815056534433717444">"שלח"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"אבג"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"לא הוזן טקסט"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"קוד מקש %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift מופעל"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock מופעל"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift פועל (הקש כדי להשבית)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock פועל (הקש כדי להשבית)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"מחק"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"סמלים"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"אותיות"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"קלט קולי"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"פרצוף סמיילי"</string> <string name="spoken_description_return" msgid="8178083177238315647">"חזור"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"פסיק"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"נקודה"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"סוגריים שמאליים"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"סוגריים ימניים"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"נקודתיים"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"נקודה פסיק"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"סימן קריאה"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"סימן שאלה"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"מרכאות כפולות"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"גרש בודד"</string> <string name="spoken_description_dot" msgid="40711082435231673">"נקודה"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"שורש ריבועי"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"פאי"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"דלתה"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"סימן מסחרי"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"לכבוד"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"כוכב"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"סולמית"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"שלוש נקודות"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"מרכאות כפולות תחתונות"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift מופעל"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock מופעל"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift מושבת"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"מצב סמלים"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"מצב אותיות"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"מצב טלפון"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"מצב סמלי טלפון"</string> <string name="voice_warning_title" msgid="4419354150908395008">"קלט קולי"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"קלט קולי אינו נתמך בשלב זה בשפתך, אך הוא פועל באנגלית."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"קלט קולי משתמש בזיהוי דיבור של Google. "<a href="http://m.google.com/privacy">"מדיניות הפרטיות של \'Google לנייד\'"</a>" חלה במקרה זה."</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"הפוך משוב ממשתמשים לפעיל"</string> <string name="prefs_description_log" msgid="5827825607258246003">"עזור לשפר את עורך שיטת הקלט על ידי שליחה אוטומטית של סטטיסטיקת שימוש ודוחות קריסת מחשב ל-Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"עיצוב מקלדת"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"מקלדת QWERTY גרמנית"</string> <string name="subtype_en_GB" msgid="88170601942311355">"אנגלית (בריטניה)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"אנגלית (ארה\"ב)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"מצב מחקר שימושיות"</string> diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index 540bb4688..052c4c8db 100644 --- a/java/res/values-ja/strings.xml +++ b/java/res/values-ja/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Androidキーボード"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androidキーボード(AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Androidキーボードの設定"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"入力オプション"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Androidスペルチェッカー"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Androidスペルチェッカー"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Androidスペルチェッカー(AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"スペルチェックの設定"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"近接データを使用"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"スペルチェックでキーボードと同じような近接アルゴリズムを使用する"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"連絡先名の検索"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"スペルチェッカーでは連絡先リストのエントリを使用します"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"キー操作バイブ"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"キー操作音"</string> <string name="popup_on_keypress" msgid="123894815723512944">"キー押下時ポップアップ"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"テキストの修正"</string> <string name="misc_category" msgid="6894192814868233453">"他のオプション"</string> <string name="advanced_settings" msgid="362895144495591463">"詳細設定"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"上級ユーザー向けオプション"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"上級者向けオプション"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"キーのポップアップ時間"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"すぐに消去"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"デフォルト"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"常に表示"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"縦向きで表示"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"常に非表示"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"設定キーを表示"</string> <string name="auto_correction" msgid="4979925752001319458">"自動修正"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"誤入力をスペースまたは句読点キーで修正する"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"OFF"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:保存しました"</string> <string name="label_go_key" msgid="1635148082137219148">"実行"</string> <string name="label_next_key" msgid="362972844525672568">"次へ"</string> + <string name="label_previous_key" msgid="1211868118071386787">"前"</string> <string name="label_done_key" msgid="2441578748772529288">"完了"</string> <string name="label_send_key" msgid="2815056534433717444">"送信"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"テキストが入力されていません"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"キーコード:%d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift有効"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock有効"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift有効(タップして解除)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock有効(タップして解除)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"DEL"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"記号"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"英字"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"音声入力"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"顔文字"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"カンマ"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"ピリオド"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左かっこ"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右かっこ"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"コロン"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"セミコロン"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"感嘆符"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"疑問符"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"二重引用符"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"単一引用符"</string> <string name="spoken_description_dot" msgid="40711082435231673">"中点"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"円周率記号"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"デルタ"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"商標記号"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"宛名記号"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"アスタリスク"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"ナンバー記号"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略記号"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"下付き二重引用符"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift有効"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock有効"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift解除"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"記号モード"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"英数モード"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"電話モード"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"電話記号モード"</string> <string name="voice_warning_title" msgid="4419354150908395008">"音声入力"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"音声入力は現在英語には対応していますが、日本語には対応していません。"</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"音声入力ではGoogleの音声認識技術を利用します。"<a href="http://m.google.com/privacy">"モバイルプライバシーポリシー"</a>"が適用されます。"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"ユーザーフィードバックを有効にする"</string> <string name="prefs_description_log" msgid="5827825607258246003">"IMEの機能向上のため、使用統計状況やクラッシュレポートをGoogleに自動送信します。"</string> <string name="keyboard_layout" msgid="8451164783510487501">"キーボードのテーマ"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"ドイツ語QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"英語(英国)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"英語(米国)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使いやすさの研究モード"</string> diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index bc2b6289c..8ec334d24 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android 키보드"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 키보드(AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android 키보드 설정"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"입력 옵션"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android 교정"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 맞춤법 검사기"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 맞춤법 검사기(AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"맞춤법 검사 설정"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"근접 데이터 사용"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"맞춤법 검사에 대해 키보드와 유사한 근접 알고리즘 사용"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"연락처 이름 조회"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"맞춤법 검사기가 주소록의 항목을 사용합니다."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"키를 누를 때 진동 발생"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"키를 누를 때 소리 발생"</string> <string name="popup_on_keypress" msgid="123894815723512944">"키를 누를 때 팝업"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"텍스트 수정"</string> <string name="misc_category" msgid="6894192814868233453">"기타 옵션"</string> <string name="advanced_settings" msgid="362895144495591463">"고급 설정"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"전문 사용자용 옵션"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"전문가용 옵션"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"키 팝업 해제 지연"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"지연 없음"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"기본값"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"항상 표시"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"세로 화면일 때만 표시"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"항상 숨기기"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"설정 키 표시"</string> <string name="auto_correction" msgid="4979925752001319458">"자동 수정"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"스페이스바와 문장부호 키를 사용하면 오타가 자동으로 교정됩니다."</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"사용 안함"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: 저장됨"</string> <string name="label_go_key" msgid="1635148082137219148">"이동"</string> <string name="label_next_key" msgid="362972844525672568">"다음"</string> + <string name="label_previous_key" msgid="1211868118071386787">"이전"</string> <string name="label_done_key" msgid="2441578748772529288">"완료"</string> <string name="label_send_key" msgid="2815056534433717444">"전송"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"입력한 텍스트 없음"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"키 코드 %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"시프트 키"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 키 누름"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock 키 켜짐"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 사용(사용하지 않으려면 탭하세요.)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock 사용(사용하지 않으려면 탭하세요.)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"삭제 키"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"기호"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"문자"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"음성 입력"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"웃는 얼굴"</string> <string name="spoken_description_return" msgid="8178083177238315647">"리턴 키"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"쉼표"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"마침표"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"왼쪽 괄호"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"오른쪽 괄호"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"콜론"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"세미콜론"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"느낌표"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"물음표"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"큰따옴표"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"작은따옴표"</string> <string name="spoken_description_dot" msgid="40711082435231673">"점"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"제곱근"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"파이"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"델타"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"상표(™)"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"퍼센트 키"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"별표"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"파운드"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"생략 부호"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"아래쪽 큰따옴표"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 사용"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock 사용"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 사용중지"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"기호 모드"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"문자 모드"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"다이얼 모드"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"전화 기호 모드"</string> <string name="voice_warning_title" msgid="4419354150908395008">"음성 입력"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"음성 입력은 현재 자국어로 지원되지 않으며 영어로 작동됩니다."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"음성 입력에서는 Google의 음성 인식 기능을 사용합니다. "<a href="http://m.google.com/privacy">"모바일 개인정보취급방침"</a>"이 적용됩니다."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"사용자 의견 사용"</string> <string name="prefs_description_log" msgid="5827825607258246003">"사용 통계 및 충돌 보고서를 Google에 자동으로 전송하여 입력 방법 편집기의 개선에 도움을 줍니다."</string> <string name="keyboard_layout" msgid="8451164783510487501">"키보드 테마"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"독일어 QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"영어(영국)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"영어(미국)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"가용성 연구 모드"</string> diff --git a/java/res/values-ky/donottranslate-more-keys.xml b/java/res/values-ky/donottranslate-more-keys.xml new file mode 100644 index 000000000..b67a9f15d --- /dev/null +++ b/java/res/values-ky/donottranslate-more-keys.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U --> + <string name="more_keys_for_cyrillic_u">ү</string> + <!-- U+04A3: "ң" CYRILLIC SMALL LETTER EN WITH DESCENDER --> + <string name="more_keys_for_cyrillic_en">ң</string> + <!-- U+04E9: "ө" CYRILLIC SMALL LETTER BARRED O --> + <string name="more_keys_for_cyrillic_o">ө</string> +</resources> diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml index 4a5c5a44c..73192d944 100644 --- a/java/res/values-land/dimens.xml +++ b/java/res/values-land/dimens.xml @@ -53,19 +53,20 @@ <fraction name="key_hint_label_ratio">52%</fraction> <fraction name="key_uppercase_letter_ratio">40%</fraction> <fraction name="key_preview_text_ratio">90%</fraction> + <fraction name="spacebar_text_ratio">40.000%</fraction> <dimen name="key_preview_offset">0.08in</dimen> <dimen name="key_preview_offset_ics">0.01in</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-0.140in</dimen> <dimen name="suggestions_strip_height">36dip</dimen> <dimen name="more_suggestions_row_height">36dip</dimen> <integer name="max_more_suggestions_row">2</integer> <fraction name="min_more_suggestions_width">60%</fraction> - <!-- key_preview_backing_height = more_suggestions_row_height * max_more_suggestions_row --> - <dimen name="key_preview_backing_height">72dip</dimen> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> <!-- popup_key_height x 1.2 --> - <dimen name="mini_keyboard_slide_allowance">0.336in</dimen> + <dimen name="more_keys_keyboard_slide_allowance">0.336in</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-0.280in</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-0.280in</dimen> </resources> diff --git a/java/res/values-lt/donottranslate-more-keys.xml b/java/res/values-lt/donottranslate-more-keys.xml index 6b81e4509..1491d954e 100644 --- a/java/res/values-lt/donottranslate-more-keys.xml +++ b/java/res/values-lt/donottranslate-more-keys.xml @@ -18,11 +18,90 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ą,à,á,â,ä,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,ė,ę,è,é,ê,ë,ē</string> - <string name="more_keys_for_i">8,į,î,ï,ì,í,ī</string> - <string name="more_keys_for_u">7,ų,ū,û,ü,ù,ú</string> - <string name="more_keys_for_s">š,ß,ś</string> - <string name="more_keys_for_c">č,ç,ć</string> - <string name="more_keys_for_z">ž,ź,ż</string> + <!-- U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="more_keys_for_a">ą,ä,ā,à,á,â,ã,å,æ</string> + <!-- U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+011B: "ě" LATIN SMALL LETTER E WITH CARON --> + <string name="more_keys_for_e">ė,ę,ē,è,é,ê,ë,ě</string> + <!-- U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+0131: "ı" LATIN SMALL LETTER DOTLESS I --> + <string name="more_keys_for_i">į,ī,ì,í,î,ï,ı</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+0153: "œ" LATIN SMALL LIGATURE OE + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_o">ö,õ,ò,ó,ô,œ,ő,ø</string> + <!-- U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE --> + <string name="more_keys_for_u">ū,ų,ü,ū,ù,ú,û,ů,ű</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA --> + <string name="more_keys_for_s">š,ß,ś,ş</string> + <!-- U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ņ,ñ,ń,ń</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ç,ć</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON --> + <string name="more_keys_for_d">ď</string> + <!-- U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + U+0159: "ř" LATIN SMALL LETTER R WITH CARON + U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE --> + <string name="more_keys_for_r">ŗ,ř,ŕ</string> + <!-- U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + U+0165: "ť" LATIN SMALL LETTER T WITH CARON --> + <string name="more_keys_for_t">ţ,ť</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE --> + <string name="more_keys_for_z">ž,ż,ź</string> + <!-- U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA --> + <string name="more_keys_for_k">ķ</string> + <!-- U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + U+013E: "ľ" LATIN SMALL LETTER L WITH CARON --> + <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string> + <!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE --> + <string name="more_keys_for_g">ģ,ğ</string> </resources> diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml index 6263f6706..09b017a12 100644 --- a/java/res/values-lt/strings.xml +++ b/java/res/values-lt/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"„Android“ klaviatūra"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"„Android“ klaviatūra (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"„Android“ klaviatūros nustatymai"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Įvesties parinktys"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"„Android“ korekcijos"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"„Android“ rašybos tikrinimo programa"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"„Android“ rašybos tikrinimo programa (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Rašybos tikrinimo nustatymai"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Naudoti artimumo duomenis"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Naudokite klaviatūros tipo artimumo algoritmą rašybai patikrinti"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktų vardų paieška"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Rašybos tikrinimo progr. naudoja įrašus, esančius kontaktų sąraše"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Klavišo paspaudimo garsas"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Iššoka paspaudus klavišą"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Teksto taisymas"</string> <string name="misc_category" msgid="6894192814868233453">"Kitos parinktys"</string> <string name="advanced_settings" msgid="362895144495591463">"Išplėstiniai nustatymai"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Parinktys ekspertams"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Parinktys ekspertams"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pagr. išš. l. atsis. d."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Be delsos"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visada rodyti"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Rodyti stačiuoju režimu"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Visada slėpti"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Rodyti nustatymų raktą"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatinis taisymas"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Tarpo kl. ir skyr. ženkl. aut. išt. neteis. įv. žodž."</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Išjungta"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: išsaugota"</string> <string name="label_go_key" msgid="1635148082137219148">"Pradėti"</string> <string name="label_next_key" msgid="362972844525672568">"Kitas"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Anks."</string> <string name="label_done_key" msgid="2441578748772529288">"Atlikta"</string> <string name="label_send_key" msgid="2815056534433717444">"Siųsti"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nėra įvesto teksto"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Klavišo kodas %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Antrojo lygio klavišas"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Antrojo lygio klavišas įgalintas"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Įgalintas didžiųjų raidžių klavišas"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Įjungtas antrasis lygis (palieskite, kad išjungtumėte)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Įjungtos didžiosios raidės (palieskite, kad išjungtumėte)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Ištrinti"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboliai"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Raidės"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Įvestis balsu"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Šypsenėlė"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Grįžti"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Kablelis"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Taškas"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kairysis skliaustas"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Dešinysis skliaustas"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dvitaškis"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Kabliataškis"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Šauktukas"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Klaustukas"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvigubos kabutės"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Viengubos kabutės"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Taškas"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratinė šaknis"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Prekės ženklas"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Perduoti"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Pažymėti žvaigždute"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Svaras"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Daugtaškis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Apatinės dvigubos kabutės"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Įgalintas antrasis lygis"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Įgalintos didžiosios raidės"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Antrasis lygis išjungtas"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simbolių režimas"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Raidžių režimas"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefono režimas"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefono simbolių režimas"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Balso įvestis"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Šiuo metu balso įvestis jūsų kompiuteryje nepalaikoma, bet ji veikia anglų k."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Balso įvesčiai naudojamas „Google“ kalbos atpažinimas. Taikoma "<a href="http://m.google.com/privacy">"privatumo politika mobiliesiems"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Įgalinti naudotojų atsiliepimus"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Padėkite patobulinti šią įvesties metodo redagavimo programą automatiškai „Google“ siųsdami naudojimo statistiką ir strigčių ataskaitas."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatūros tema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Vokiška QWERTY klaviatūra"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Anglų k. (JK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Anglų k. (JAV)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tinkamumo tyrimo režimas"</string> diff --git a/java/res/values-lv/donottranslate-more-keys.xml b/java/res/values-lv/donottranslate-more-keys.xml index 77e1c26a0..d0a44480a 100644 --- a/java/res/values-lv/donottranslate-more-keys.xml +++ b/java/res/values-lv/donottranslate-more-keys.xml @@ -18,16 +18,89 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ā,à,á,â,ä,æ,ã,å</string> - <string name="more_keys_for_e">3,ē,è,é,ê,ë,ę,ė</string> - <string name="more_keys_for_i">8,ī,î,ï,ì,í,į</string> - <string name="more_keys_for_u">7,ū,û,ü,ù,ú</string> - <string name="more_keys_for_s">š,ß,ś</string> - <string name="more_keys_for_n">ņ,ñ,ń</string> - <string name="more_keys_for_c">č,ç,ć</string> - <string name="more_keys_for_r">4,ŗ</string> - <string name="more_keys_for_z">ž,ź,ż</string> - <string name="more_keys_for_k">ķ</string> - <string name="more_keys_for_l">ļ,ł</string> - <string name="more_keys_for_g">ģ</string> + <!-- U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+00E6: "æ" LATIN SMALL LETTER AE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK --> + <string name="more_keys_for_a">ā,à,á,â,ã,ä,å,æ,ą</string> + <!-- U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+011B: "ě" LATIN SMALL LETTER E WITH CARON --> + <string name="more_keys_for_e">ē,ė,è,é,ê,ë,ę,ě</string> + <!-- U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+0131: "ı" LATIN SMALL LETTER DOTLESS I --> + <string name="more_keys_for_i">ī,į,ì,í,î,ï,ı</string> + <!-- U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+0153: "œ" LATIN SMALL LIGATURE OE + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_o">ò,ó,ô,õ,ö,œ,ő,ø</string> + <!-- U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE --> + <string name="more_keys_for_u">ū,ų,ù,ú,û,ü,ů,ű</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA --> + <string name="more_keys_for_s">š,ß,ś,ş</string> + <!-- U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ņ,ñ,ń,ń</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ç,ć</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON --> + <string name="more_keys_for_d">ď</string> + <!-- U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + U+0159: "ř" LATIN SMALL LETTER R WITH CARON + U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE --> + <string name="more_keys_for_r">ŗ,ř,ŕ</string> + <!-- U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + U+0165: "ť" LATIN SMALL LETTER T WITH CARON --> + <string name="more_keys_for_t">ţ,ť</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE --> + <string name="more_keys_for_z">ž,ż,ź</string> + <!-- U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA --> + <string name="more_keys_for_k">ķ</string> + <!-- U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE + U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + U+013E: "ľ" LATIN SMALL LETTER L WITH CARON --> + <string name="more_keys_for_l">ļ,ł,ĺ,ľ</string> + <!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE --> + <string name="more_keys_for_g">ģ,ğ</string> </resources> diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml index af01d92f6..d358a8485 100644 --- a/java/res/values-lv/strings.xml +++ b/java/res/values-lv/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android tastatūra"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android tastatūra (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android tastatūras iestatījumi"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Ievades opcijas"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android korekcija"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android pareizrakstības pārbaudītājs"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android pareizrakstības pārbaudītājs (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Pareizrakstības pārbaudes iestatījumi"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Tuvuma datu izmantošana"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Pareizrakstības pārbaudei izmantojiet tastatūrai līdzīgu tuvuma algoritmu."</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Meklēt kontaktp. vārdus"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Pareizrakst. pārbaudītājs lieto ierakstus no kontaktp. saraksta."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Skaņa, nospiežot taustiņu"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Nospiežot taustiņu, parādīt uznirstošo izvēlni"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Teksta korekcija"</string> <string name="misc_category" msgid="6894192814868233453">"Citas opcijas"</string> <string name="advanced_settings" msgid="362895144495591463">"Papildu iestatījumi"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcijas speciālistiem"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcijas ekspertiem"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Taust. uzn. loga noraid. aizk."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez aizkaves"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vienmēr rādīt"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Rādīt portreta režīmā"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vienmēr slēpt"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Rādīt iestatījumu taustiņu"</string> <string name="auto_correction" msgid="4979925752001319458">"Automāt. korekcija"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Atstarpes taustiņš un interpunkcija; automātiska kļūdainu vārdu labošana"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Izslēgta"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: saglabāts"</string> <string name="label_go_key" msgid="1635148082137219148">"Sākt"</string> <string name="label_next_key" msgid="362972844525672568">"Tālāk"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Iepr."</string> <string name="label_done_key" msgid="2441578748772529288">"Gatavs"</string> <string name="label_send_key" msgid="2815056534433717444">"Sūtīt"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nav ievadīts teksts"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Taustiņu kods %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Pārslēgšanas taustiņš"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Pārslēgšanas taustiņš iespējots"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Burtslēgs iespējots"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Pārslēgšanas taustiņš iespējots (pieskarieties, lai atspējotu)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Burtslēgs iespējots (pieskarieties, lai atspējotu)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Dzēšanas taustiņš"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Burti"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Balss ievade"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smaidoša seja"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Ievadīšanas taustiņš"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komats"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punkts"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kreisā iekava"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Labā iekava"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kols"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikols"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Izsaukuma zīme"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Jautājuma zīme"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Pēdiņas"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Vienpēdiņas"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punkts"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadrātsakne"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pī"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Preču zīme"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Zvaigznīte"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Cipara simbols"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Daudzpunkte"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Apakšējās pēdiņas"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pārslēgšanas režīms iespējots"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Burtslēgs iespējots"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Pārslēgšanas režīms atspējots"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Simbolu režīms"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Burtu režīms"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Tālruņa režīms"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Tālruņa simbolu režīms"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Balss ievade"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Balss ievade jūsu valodā pašlaik netiek atbalstīta, taču tā ir pieejama angļu valodā."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Balss ievadei tiek izmantota Google runas atpazīšanas funkcija. Uz šīs funkcijas lietošanu attiecas "<a href="http://m.google.com/privacy">"mobilo sakaru ierīču lietošanas konfidencialitātes politika"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Iespējot lietotāju atsauksmes"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Palīdziet uzlabot šo ievades metodes redaktoru, automātiski nosūtot lietojuma statistiku un pārskatus par avārijām uzņēmumam Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tastatūras motīvs"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Vācu valodas QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Angļu valoda (Lielbritānija)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Angļu valoda (ASV)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Lietojamības izpētes režīms"</string> diff --git a/java/res/values-mk/donottranslate-more-keys.xml b/java/res/values-mk/donottranslate-more-keys.xml new file mode 100644 index 000000000..e96a306b6 --- /dev/null +++ b/java/res/values-mk/donottranslate-more-keys.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- NOTE: Macedonian layouts are based on Serbian ones with the following key replacements. --> + <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE --> + <string name="keylabel_for_cyrillic_ze">ѕ</string> + <!-- U+045C: "ќ" CYRILLIC SMALL LETTER KJE --> + <string name="keylabel_for_cyrillic_tshe">ќ</string> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <string name="keylabel_for_cyrillic_dze">з</string> + <!-- U+0453: "ѓ" CYRILLIC SMALL LETTER GJE --> + <string name="keylabel_for_cyrillic_dje">ѓ</string> + <!-- U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE --> + <string name="more_keys_for_cyrillic_ie">ѐ</string> + <!-- U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE --> + <string name="more_keys_for_cyrillic_i">ѝ</string> + <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. --> + <!-- <string name="more_keys_for_double_quote">!fixedColumnOrder!6,„,“,”,‟,«,»</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!5,„,“,”,«,»</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!5,„,“,”,«,»,‘,’,‚,‛</string> +</resources> diff --git a/java/res/values-ms/strings.xml b/java/res/values-ms/strings.xml index d6bf559e7..246c4d7a0 100644 --- a/java/res/values-ms/strings.xml +++ b/java/res/values-ms/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Papan kekunci Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Papan kekunci Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Tetapan papan kekunci Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Pilihan input"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Pembetulan Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Penyemak ejaan Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Penyemak ejaan Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Tetapan penyemakan ejaan"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Gunakan data kehampiran"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gunakan algoritma kehampiran ala papan kekunci untuk pemeriksaan ejaan"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Cari nama kenalan"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Penyemak ejaan menggunakan entri dari senarai kenalan anda"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Bunyi pada tekanan kekunci"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop timbul pada tekanan kunci"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"Pembetulan teks"</string> <string name="misc_category" msgid="6894192814868233453">"Pilihan lain"</string> <string name="advanced_settings" msgid="362895144495591463">"Tetapan terperinci"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Pilihan untuk pengguna pakar"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Pilihan untuk pakar"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Tukar ke kaedah input lain"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kunci pertukaran bahasa meliputi kaedah masukan lain juga"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Tekan kunci ptukaran bhs"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pop tmbl knci ketpkn lengah"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tiada lengah"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Sentiasa tunjukkan"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Tunjukkan pada mod potret"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sentiasa sembunyikan"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Tunjukkan kekunci tetapan"</string> <string name="auto_correction" msgid="4979925752001319458">"Auto Pembetulan"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Bar ruang dan tanda baca secara automatik membetulkan perkataan yang ditaip salah"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Matikan"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Disimpan"</string> <string name="label_go_key" msgid="1635148082137219148">"Pergi"</string> <string name="label_next_key" msgid="362972844525672568">"Seterusnya"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Sblm"</string> <string name="label_done_key" msgid="2441578748772529288">"Selesai"</string> <string name="label_send_key" msgid="2815056534433717444">"Hantar"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Tiada teks dimasukkan"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kod kunci %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift didayakan"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Kunci huruf besar didayakan"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kunci anjak dihidupkan (ketik untuk melumpuhkan)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kunci huruf besar dihidupkan (ketik untuk melumpuhkan)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Padam"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simbol"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Huruf"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Input suara"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Muka senyum"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Tempoh"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Tanda kurung kiri"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Tanda kurung kanan"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Titik bertindih"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Koma bertitik"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tanda seru"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tanda soal"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Tanda petikan berganda"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Tanda petikan tunggal"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Titik"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Punca kuasa dua"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Tanda dagangan"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Dengan alamat"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Bintang"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Paun"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Elipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Tanda petikan berganda rendah"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kunci anjak didayakan"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kunci huruf besar didayakan"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kunci anjak dilumpuhkan"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mod simbol"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mod huruf"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mod telefon"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mod simbol telefon"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Input suara"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Input suara tidak disokong untuk bahasa anda pada masa ini tetapi ia berfungsi dalam bahasa Inggeris."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Input suara menggunakan pengecaman pertuturan Google. "<a href="http://m.google.com/privacy">"Dasar Privasi Mudah Alih"</a>" digunakan."</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Dayakan maklum balas pengguna"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Bantu memperbaik editor input ini dengan menghantar statistik penggunaan dan laporan runtuhan kepada Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema papan kekunci"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY Bahasa Jerman"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Bahasa Inggeris (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Bahasa Inggeris (AS)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Mod kajian kebolehgunaan"</string> diff --git a/java/res/values-nb/donottranslate-more-keys.xml b/java/res/values-nb/donottranslate-more-keys.xml index b98341c6a..7248d983e 100644 --- a/java/res/values-nb/donottranslate-more-keys.xml +++ b/java/res/values-nb/donottranslate-more-keys.xml @@ -18,12 +18,43 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,ä,á,â,ã,ā</string> - <string name="more_keys_for_e">3,é,è,ê,ë,ę,ė,ē</string> - <string name="more_keys_for_o">9,ô,ò,ó,ö,õ,œ,ō</string> - <string name="more_keys_for_u">7,ü,û,ù,ú,ū</string> - <string name="keylabel_for_scandinavia_row2_10">ø</string> - <string name="keylabel_for_scandinavia_row2_11">æ</string> - <string name="more_keys_for_scandinavia_row2_10">ö</string> - <string name="more_keys_for_scandinavia_row2_11">ä</string> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">à,ä,á,â,ã,ā</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,è,ê,ë,ę,ė,ē</string> + <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ô,ò,ó,ö,õ,œ,ō</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ü,û,ù,ú,ū</string> + <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE --> + <string name="keylabel_for_scandinavia_row1_11">å</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="keylabel_for_scandinavia_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="keylabel_for_scandinavia_row2_11">æ</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="more_keys_for_scandinavia_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="more_keys_for_scandinavia_row2_11">ä</string> </resources> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index acd636bdd..8114cd50c 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Skjermtastatur"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-tastatur (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Innstillinger for skjermtastatur"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Inndataalternativer"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-stavekontroll"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android-stavekontroll"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android-stavekontroll (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Innstillinger for stavekontroll"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Bruk nærhetsdata"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Bruk en tastaturlignende algoritme til stavekontroll"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Slå opp kontaktnavn"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Stavekontrollen bruker oppføringer fra kontaktlisten din"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetrykk"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Hurtigvindu ved tastetrykk"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Tekstkorrigering"</string> <string name="misc_category" msgid="6894192814868233453">"Andre alternativer"</string> <string name="advanced_settings" msgid="362895144495591463">"Avanserte innstillinger"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Alternativer for ekspertbrukere"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Alternativer for eksperter"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tregt tastevindu"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"U/ forsinkelse"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis alltid"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Vis i stående modus"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul alltid"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Vis innstillingsnøkkel"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatisk retting"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Mellomromstast og skilletegn retter automat. feilstavede ord"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Av"</string> @@ -62,8 +69,9 @@ <string name="bigram_prediction" msgid="8914273444762259739">"Bigram-prediksjon"</string> <string name="bigram_prediction_summary" msgid="1747261921174300098">"Bruk forrige ord også for forslag"</string> <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: Lagret"</string> - <string name="label_go_key" msgid="1635148082137219148">"Gå"</string> + <string name="label_go_key" msgid="1635148082137219148">"Utfør"</string> <string name="label_next_key" msgid="362972844525672568">"Neste"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Forr."</string> <string name="label_done_key" msgid="2441578748772529288">"Utfør"</string> <string name="label_send_key" msgid="2815056534433717444">"Send"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Ingen tekst er skrevet inn"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Tastaturkode %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift er aktivert"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock er aktivert"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift er på (trykk for å deaktivere)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock er på (trykk for å deaktivere)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Slett"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Bokstaver"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Taleinndata"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smilefjes"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punktum"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Venstre parentes"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Høyre parentes"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Utropstegn"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Spørsmålstegn"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dobbelt anførselstegn"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkelt anførselstegn"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Prikk"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrot"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Varemerke"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"c/o"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Stjerne"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Firkant"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipse"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lavt dobbelt anførselstegn"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift er aktivert"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock er aktivert"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift er deaktivert"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolmodus"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bokstavmodus"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Ringemodus"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Ringemodus med symboler"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Stemmedata"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Stemmedata håndteres foreløpig ikke på ditt språk, men fungerer på engelsk."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Google Voice bruker Googles talegjenkjenning. "<a href="http://m.google.com/privacy">"Personvernreglene for mobil"</a>" gjelder."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktiver brukertilbakemelding"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ved å sende bruksstatistikk og programstopprapporter til Google automatisk, hjelper du oss med å gjøre redigeringsfunksjonen for denne inndatametoden enda bedre."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Tysk QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannia)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Nyttighetsmodus"</string> diff --git a/java/res/values-nl/donottranslate-more-keys.xml b/java/res/values-nl/donottranslate-more-keys.xml index 49cc41964..4f5cbee55 100644 --- a/java/res/values-nl/donottranslate-more-keys.xml +++ b/java/res/values-nl/donottranslate-more-keys.xml @@ -18,10 +18,46 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,ä,â,à,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,é,ë,ê,è,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,ï,ì,î,į,ī</string> - <string name="more_keys_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string> - <string name="more_keys_for_u">7,ú,ü,û,ù,ū</string> - <string name="more_keys_for_n">ñ,ń</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">á,ä,â,à,æ,ã,å,ā</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">é,ë,ê,è,ę,ė,ē</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,ï,ì,î,į,ī</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ó,ö,ô,ò,õ,œ,ø,ō</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,û,ù,ū</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ñ,ń</string> </resources> diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index 7f0ff7eaf..56d423a29 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android-toetsenbord"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android-toetsenbord (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Instellingen voor Android-toetsenbord"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Invoeropties"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-spellingcontrole"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Spellingcontrole van Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Spellingcontrole van Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Instellingen voor spellingcontrole"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Nabije toetsinfo gebr."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Algoritme voor nabije toetsen gebruiken voor spellingcontrole"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Contactnamen opzoeken"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"De spellingcontrole gebruikt items uit uw contactenlijst"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Geluid bij toetsaanslag"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bij toetsaanslag"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Tekstcorrectie"</string> <string name="misc_category" msgid="6894192814868233453">"Andere opties"</string> <string name="advanced_settings" msgid="362895144495591463">"Geavanceerde instellingen"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opties voor ervaren gebruikers"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opties voor experts"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Afwijz.vertr. toetspop-up"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen vertraging"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Altijd weergeven"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Weergeven in staande modus"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Altijd verbergen"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Instellingscode weergeven"</string> <string name="auto_correction" msgid="4979925752001319458">"Autocorrectie"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Met spatiebalk en interpunctie worden verkeerd gespelde woorden automatisch gecorrigeerd"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Uitgeschakeld"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: opgeslagen"</string> <string name="label_go_key" msgid="1635148082137219148">"Start"</string> <string name="label_next_key" msgid="362972844525672568">"Verder"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Vorig"</string> <string name="label_done_key" msgid="2441578748772529288">"Gereed"</string> <string name="label_send_key" msgid="2815056534433717444">"Zenden"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Geen tekst ingevoerd"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Toetscode %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift ingeschakeld"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock ingeschakeld"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift aan (tik om uit te schakelen)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock aan (tik om uit te schakelen)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Verwijderen"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbolen"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letters"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Spraakinvoer"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley-gezichtje"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punt"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Linkerhaakje"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Rechterhaakje"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dubbele punt"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Puntkomma"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uitroepteken"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vraagteken"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbele aanhalingstekens"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkel aanhalingsteken"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Stip"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Vierkantswortel"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Handelsmerk"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Ten attentie van"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Ster"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Hekje"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Weglatingsteken"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Lage dubbele aanhalingstekens"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ingeschakeld"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock ingeschakeld"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift uitgeschakeld"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolen"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Alfanumeriek toetsenbord"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Toetsenbord telefoon"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefoonsymbolen"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Spraakinvoer"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Spraakinvoer wordt momenteel niet ondersteund in uw taal, maar is wel beschikbaar in het Engels."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Spraakinvoer maakt gebruik van de spraakherkenning van Google. Het "<a href="http://m.google.com/privacy">"Privacybeleid van Google Mobile"</a>" is van toepassing."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Gebruikersfeedback inschakelen."</string> <string name="prefs_description_log" msgid="5827825607258246003">"Help deze invoermethode te verbeteren door automatisch gebruiksstatistieken en crashmeldingen naar Google te verzenden."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Toetsenbordthema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Duits QWERTY-toetsenbord"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engels (GB)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modus voor gebruiksvriendelijkheidsonderzoek"</string> diff --git a/java/res/values-pl/donottranslate-more-keys.xml b/java/res/values-pl/donottranslate-more-keys.xml index 18e149991..0f8a59bd6 100644 --- a/java/res/values-pl/donottranslate-more-keys.xml +++ b/java/res/values-pl/donottranslate-more-keys.xml @@ -18,12 +18,48 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ą,á,à,â,ä,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,ę,è,é,ê,ë,ė,ē</string> - <string name="more_keys_for_o">9,ó,ö,ô,ò,õ,œ,ø,ō</string> - <string name="more_keys_for_s">ś,ß,š</string> - <string name="more_keys_for_n">ń,ñ</string> - <string name="more_keys_for_c">ć,ç,č</string> - <string name="more_keys_for_z">ż,ź,ž</string> - <string name="more_keys_for_l">ł</string> + <!-- U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">ą,á,à,â,ä,æ,ã,å,ā</string> + <!-- U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON --> + <string name="more_keys_for_e">ę,è,é,ê,ë,ė,ē</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ó,ö,ô,ò,õ,œ,ø,ō</string> + <!-- U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ś,ß,š</string> + <!-- U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE --> + <string name="more_keys_for_n">ń,ñ</string> + <!-- U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ć,ç,č</string> + <!-- U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + U+017E: "ž" LATIN SMALL LETTER Z WITH CARON --> + <string name="more_keys_for_z">ż,ź,ž</string> + <!-- U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> + <string name="more_keys_for_l">ł</string> </resources> diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index a9a6a76b6..ec9e01441 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Klawiatura Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klawiatura Androida (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Ustawienia klawiatury Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opcje wprowadzania"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Korekta Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Sprawdzanie pisowni na Androidzie"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Sprawdzanie pisowni na Androidzie (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Ustawienia sprawdzania pisowni"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Użyj danych o klawiszach"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Przy sprawdzaniu pisowni używaj algorytmu uwzględniającego położenie klawiszy na klawiaturze"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Przeszukaj nazwy kontaktów"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Sprawdzanie pisowni bierze pod uwagę wpisy z listy kontaktów."</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Dźwięk przy naciśnięciu"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Powiększ po naciśnięciu"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Poprawianie tekstu"</string> <string name="misc_category" msgid="6894192814868233453">"Inne opcje"</string> <string name="advanced_settings" msgid="362895144495591463">"Ustawienia zaawansowane"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opcje dla zaawansowanych użytkowników"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opcje dla ekspertów"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Opóźnienie znikania klawiszy"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez opóźnienia"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartość domyślna"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Zawsze pokazuj"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Pokaż w trybie pionowym"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Zawsze ukrywaj"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Pokaż klawisz ustawień"</string> <string name="auto_correction" msgid="4979925752001319458">"Autokorekta"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Spacja i znaki przestankowe poprawiają błędnie wpisane słowa"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Wyłącz"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Zapisano"</string> <string name="label_go_key" msgid="1635148082137219148">"OK"</string> <string name="label_next_key" msgid="362972844525672568">"Dalej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Wstecz"</string> <string name="label_done_key" msgid="2441578748772529288">"OK"</string> <string name="label_send_key" msgid="2815056534433717444">"Wyślij"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nie wprowadzono tekstu"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kod klawisza: %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift włączony"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock włączony"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift włączony (kliknij, by wyłączyć)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock włączony (kliknij, by wyłączyć)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Usuń"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symbole"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Litery"</string> @@ -88,29 +96,17 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Wprowadzanie głosowe"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Uśmiechnięta buźka"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Przecinek"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Kropka"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Lewy nawias"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Prawy nawias"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dwukropek"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Średnik"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Wykrzyknik"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Pytajnik"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Cudzysłów podwójny"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Cudzysłów pojedynczy"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Pierwiastek kwadratowy"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Znak towarowy"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Znak „przez grzeczność”"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Gwiazdka"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Krzyżyk"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Wielokropek"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Cudzysłów podwójny dolny"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift włączony"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock włączony"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift wyłączony"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Tryb symboli"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Tryb liter"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Tryb telefonu"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Tryb symboli telefonu"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Wprowadzanie głosowe"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Wprowadzanie głosowe obecnie nie jest obsługiwane w Twoim języku, ale działa w języku angielskim."</string> - <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Funkcja wprowadzania głosowego wykorzystuje mechanizm rozpoznawania mowy. Obowiązuje "<a href="http://m.google.com/privacy">"Polityka prywatności Google Mobile"</a>"."</string> + <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Funkcja wprowadzania głosowego wykorzystuje mechanizm rozpoznawania mowy. Obowiązuje "<a href="http://m.google.com/privacy">"Polityka prywatności w usługach mobilnych"</a>"."</string> <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Aby wyłączyć rozpoznawanie mowy, przejdź do ustawień sposobu wprowadzania tekstu."</string> <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Aby użyć wprowadzania głosowego, naciśnij przycisk mikrofonu."</string> <string name="voice_listening" msgid="467518160751321844">"Mów teraz"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Włącz przesyłanie opinii użytkownika"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Pomóż ulepszyć edytor wprowadzania tekstu, automatycznie wysyłając do Google statystyki użycia i raporty o awariach."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Motyw klawiatury"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Niemiecka QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Angielska (Wielka Brytania)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Angielska (Stany Zjednoczone)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Tryb badania przydatności"</string> diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 0a30235f4..4e0cf4c5c 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Teclado do Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Definições de teclado do Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de introdução"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Correção do Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Verificador ortográfico do Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificador ortográfico do Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Definições da verificação ortográfica"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Utilizar dados de prox."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Util. algoritmo de prox. semelhante a teclado para verif. ortog."</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Procurar nomes de contac."</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico utiliza entradas da sua lista de contactos"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Som ao premir as teclas"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Mostrar popup ao premir tecla"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Correção de texto"</string> <string name="misc_category" msgid="6894192814868233453">"Outras opções"</string> <string name="advanced_settings" msgid="362895144495591463">"Definições avançadas"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opções para utilizadores experientes"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opções para especialistas"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Atraso p/ ignorar pop-up"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar no modo de retrato"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar sempre"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla das definições"</string> <string name="auto_correction" msgid="4979925752001319458">"Auto correcção"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Correcção automática de palavras mal escritas c/ barra de espaços e pontuação"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desligar"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: guardada"</string> <string name="label_go_key" msgid="1635148082137219148">"OK"</string> <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Ant."</string> <string name="label_done_key" msgid="2441578748772529288">"Feito"</string> <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nenhum texto digitado"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Código da tecla %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift ativado"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock ativado"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (tocar para desativar)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock ativado (tocar para desativar)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Cara sorridente"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Vírgula"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Ponto final"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parêntese esquerdo"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parêntese direito"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dois pontos"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Ponto e vírgula"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ponto de exclamação"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ponto de interrogação"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Aspas"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Plica"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Raiz quadrada"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marca comercial"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Ao cuidado de"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Marcar com estrela"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Cardinal"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Reticências"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Aspas duplas baixas"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de letras"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de telemóvel"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de telemóvel"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Actualmente, a entrada de voz não é suportada para o seu idioma, mas funciona em inglês."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A entrada de voz utiliza o reconhecimento de voz da Google. É aplicável a "<a href="http://m.google.com/privacy">"Política de privacidade do Google Mobile"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Activar comentários do utilizador"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Envie automaticamente estatísticas de utilização e relatórios de falhas para a Google e ajude-nos a melhorar este editor de método de introdução."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY Alemão"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (RU)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo da capacidade de utilização"</string> diff --git a/java/res/values-pt/donottranslate-more-keys.xml b/java/res/values-pt/donottranslate-more-keys.xml index 31d9417ab..0c9065f27 100644 --- a/java/res/values-pt/donottranslate-more-keys.xml +++ b/java/res/values-pt/donottranslate-more-keys.xml @@ -18,10 +18,48 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">á,ã,à,â,ä,å,æ,ª</string> - <string name="more_keys_for_e">3,é,ê,è,ę,ė,ē,ë</string> - <string name="more_keys_for_i">8,í,î,ì,ï,į,ī</string> - <string name="more_keys_for_o">9,ó,õ,ô,ò,ö,œ,ø,ō,º</string> - <string name="more_keys_for_u">7,ú,ü,ù,û,ū</string> - <string name="more_keys_for_c">ç,č,ć</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+00E6: "æ" LATIN SMALL LETTER AE + U+00AA: "ª" FEMININE ORDINAL INDICATOR --> + <string name="more_keys_for_a">á,ã,à,â,ä,å,æ,ª</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS --> + <string name="more_keys_for_e">é,ê,è,ę,ė,ē,ë</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">í,î,ì,ï,į,ī</string> + <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00BA: "º" MASCULINE ORDINAL INDICATOR --> + <string name="more_keys_for_o">ó,õ,ô,ò,ö,œ,ø,ō,º</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ú,ü,ù,û,ū</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">ç,č,ć</string> </resources> diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 36a70daa6..b3af6f051 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Teclado Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Teclado Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Configurações de teclado Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opções de entrada"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Correção do Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Corretor ortográfico do Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Corretor ortográfico do Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Configurações de verificação ortográfica"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Usar dados de proximidade"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Usar algoritmo de prox. tipo teclado para verificação ortográfica"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Buscar nomes de contatos"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"O corretor ortográfico usa entradas de sua lista de contatos"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Som ao tocar a tecla"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Exibir pop-up ao digitar"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Correção de texto"</string> <string name="misc_category" msgid="6894192814868233453">"Outras opções"</string> <string name="advanced_settings" msgid="362895144495591463">"Configurações avançadas"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opções para usuários experientes"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opções para especialistas"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Dispens. atraso chave princ."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Padrão"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Mostrar em modo retrato"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sempre ocultar"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Mostrar tecla de config."</string> <string name="auto_correction" msgid="4979925752001319458">"Autocorreção"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"A barra de espaço e a pontuação corrigem automaticamente palavras com erro de digitação"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desativado"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Salvo"</string> <string name="label_go_key" msgid="1635148082137219148">"Ir"</string> <string name="label_next_key" msgid="362972844525672568">"Avançar"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Volt."</string> <string name="label_done_key" msgid="2441578748772529288">"Feito"</string> <string name="label_send_key" msgid="2815056534433717444">"Enviar"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nenhum texto digitado"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Código de tecla %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift ativado"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock ativado"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift ativado (toque para desativar)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock ativado (toque para desativar)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Excluir"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Símbolos"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Letras"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Entrada de voz"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Carinha sorridente"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Voltar"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Vírgula"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Ponto final"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Parêntese esquerdo"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Parêntese direito"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dois pontos"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Ponto e vírgula"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ponto de exclamação"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Ponto de interrogação"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Aspa dupla"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Aspa simples"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Ponto"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Raiz quadrada"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marca registrada"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Porcentagem"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Asterisco"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Sustenido"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Reticências"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Aspas duplas inferiores"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift ativado"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock ativado"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift desativado"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modo de símbolos"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modo de cartas"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modo de telefone"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modo de símbolos de telefone"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Entrada de voz"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"A entrada de voz não é suportada no momento para o seu idioma, mas funciona em inglês."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"A entrada de texto por voz usa o reconhecimento de voz do Google. "<a href="http://m.google.com/privacy">"A política de privacidade para celulares"</a>" é aplicada."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Ativar comentário do usuário"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ajude a melhorar este editor de método de entrada enviando automaticamente ao Google estatísticas de uso e relatórios de falhas."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY alemão"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (Reino Unido)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modo de estudo de utilização"</string> diff --git a/java/res/values-rm/donottranslate-more-keys.xml b/java/res/values-rm/donottranslate-more-keys.xml index ea9a55944..aa0d7f817 100644 --- a/java/res/values-rm/donottranslate-more-keys.xml +++ b/java/res/values-rm/donottranslate-more-keys.xml @@ -18,5 +18,12 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_o">9,ò,ó,ö,ô,õ,œ,ø</string> + <!-- U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_o">ò,ó,ö,ô,õ,œ,ø</string> </resources> diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml index 090f3fc47..8fcb67d46 100644 --- a/java/res/values-rm/strings.xml +++ b/java/res/values-rm/strings.xml @@ -21,16 +21,20 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Tastatura Android"</string> + <!-- no translation found for aosp_android_keyboard_ime_name (7877134937939182296) --> + <skip /> <string name="english_ime_settings" msgid="6661589557206947774">"Parameters da la tastatura Android"</string> <!-- no translation found for english_ime_input_options (3909945612939668554) --> <skip /> - <!-- no translation found for spell_checker_service_name (2003013122022285508) --> + <!-- no translation found for spell_checker_service_name (7338064335159755926) --> + <skip /> + <!-- no translation found for aosp_spell_checker_service_name (6985142605330377819) --> <skip /> <!-- no translation found for android_spell_checker_settings (5822324635435443689) --> <skip /> - <!-- no translation found for use_proximity_option_title (7469233942295924620) --> + <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) --> <skip /> - <!-- no translation found for use_proximity_option_summary (2857708859847261945) --> + <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) --> <skip /> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar cun smatgar in buttun"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Tun cun smatgar in buttun"</string> @@ -43,7 +47,13 @@ <skip /> <!-- no translation found for advanced_settings (362895144495591463) --> <skip /> - <!-- no translation found for advanced_settings_summary (5193513161106637254) --> + <!-- no translation found for advanced_settings_summary (4487980456152830271) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> <skip /> <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) --> <skip /> @@ -74,10 +84,10 @@ <skip /> <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) --> <skip /> - <!-- no translation found for prefs_settings_key (4623341240804046498) --> + <!-- no translation found for auto_correction (4979925752001319458) --> + <skip /> + <!-- no translation found for auto_correction_summary (5625751551134658006) --> <skip /> - <!-- outdated translation 7911639788808958255 --> <string name="auto_correction" msgid="4979925752001319458">"Propostas da pleds"</string> - <!-- outdated translation 6881047311475758267 --> <string name="auto_correction_summary" msgid="5625751551134658006">"Curreger automaticamain il pled precedent"</string> <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) --> <skip /> <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) --> @@ -86,7 +96,8 @@ <skip /> <!-- no translation found for auto_correction_threshold_mode_very_aggeressive (3386782235540547678) --> <skip /> - <!-- outdated translation 1323347224043514969 --> <string name="bigram_suggestion" msgid="2636414079905220518">"Propostas da tip bigram"</string> + <!-- no translation found for bigram_suggestion (2636414079905220518) --> + <skip /> <string name="bigram_suggestion_summary" msgid="4383845146070101531">"Meglierar la proposta cun agid dal pled precedent"</string> <!-- no translation found for bigram_prediction (8914273444762259739) --> <skip /> @@ -95,6 +106,8 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Memorisà"</string> <string name="label_go_key" msgid="1635148082137219148">"Dai"</string> <string name="label_next_key" msgid="362972844525672568">"Vinavant"</string> + <!-- no translation found for label_previous_key (1211868118071386787) --> + <skip /> <string name="label_done_key" msgid="2441578748772529288">"Finì"</string> <string name="label_send_key" msgid="2815056534433717444">"Trametter"</string> <!-- no translation found for label_to_alpha_key (4793983863798817523) --> @@ -117,9 +130,9 @@ <skip /> <!-- no translation found for spoken_description_shift (244197883292549308) --> <skip /> - <!-- no translation found for spoken_description_shift_shifted (954941524766465022) --> + <!-- no translation found for spoken_description_shift_shifted (1681877323344195035) --> <skip /> - <!-- no translation found for spoken_description_caps_lock (5660626444912131764) --> + <!-- no translation found for spoken_description_caps_lock (3276478269526304432) --> <skip /> <!-- no translation found for spoken_description_delete (8740376944276199801) --> <skip /> @@ -141,51 +154,30 @@ <skip /> <!-- no translation found for spoken_description_return (8178083177238315647) --> <skip /> - <!-- no translation found for spoken_description_comma (4970844442999724586) --> - <skip /> - <!-- no translation found for spoken_description_period (5286614628077903945) --> - <skip /> - <!-- no translation found for spoken_description_left_parenthesis (8524822120595052415) --> - <skip /> - <!-- no translation found for spoken_description_right_parenthesis (1085757995851933164) --> - <skip /> - <!-- no translation found for spoken_description_colon (4312420908484277077) --> - <skip /> - <!-- no translation found for spoken_description_semicolon (37737920987155179) --> - <skip /> - <!-- no translation found for spoken_description_exclamation_mark (2625684427460737157) --> - <skip /> - <!-- no translation found for spoken_description_question_mark (7074097784255379666) --> - <skip /> - <!-- no translation found for spoken_description_double_quote (5485320575389905967) --> - <skip /> - <!-- no translation found for spoken_description_single_quote (4451320362665463938) --> - <skip /> <!-- no translation found for spoken_description_dot (40711082435231673) --> <skip /> - <!-- no translation found for spoken_description_square_root (190595160284757811) --> - <skip /> - <!-- no translation found for spoken_description_pi (4554418247799952239) --> + <!-- no translation found for spoken_description_shiftmode_on (5700440798609574589) --> <skip /> - <!-- no translation found for spoken_description_delta (3607948313655721579) --> + <!-- no translation found for spoken_description_shiftmode_locked (593175803181701830) --> <skip /> - <!-- no translation found for spoken_description_trademark (475877774077871369) --> + <!-- no translation found for spoken_description_shiftmode_off (657219998449174808) --> <skip /> - <!-- no translation found for spoken_description_care_of (7492800237237796530) --> + <!-- no translation found for spoken_description_mode_symbol (7183343879909747642) --> <skip /> - <!-- no translation found for spoken_description_star (1009742725387231977) --> + <!-- no translation found for spoken_description_mode_alpha (3528307674390156956) --> <skip /> - <!-- no translation found for spoken_description_pound (5530577649206922631) --> + <!-- no translation found for spoken_description_mode_phone (6520207943132026264) --> <skip /> - <!-- no translation found for spoken_description_ellipsis (1687670869947652062) --> - <skip /> - <!-- no translation found for spoken_description_low_double_quote (3551394572784840975) --> + <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) --> <skip /> <string name="voice_warning_title" msgid="4419354150908395008">"Cumonds vocals"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"\"Cumonds vocals en Vossa lingua na vegnan actualmain betg sustegnids, ma la funcziun è disponibla per englais.\""</string> - <!-- outdated translation 4611518823070986445 --> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Ils cumonds vocals èn ina funcziunalitad experimentala che utilisescha la renconuschientscha vocala da rait da Google."</string> - <!-- outdated translation 5652369578498701761 --> <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"\"Per deactivar ils cumonds vocals, avri ils parameters da tastatura.\""</string> - <!-- outdated translation 6892342981545727994 --> <string name="voice_hint_dialog_message" msgid="1420686286820661548">"\"Per utilisar ils cumonds vocals, smatgai il buttun dal microfon u stritgai cun il det sur la tastatura dal visur.\""</string> + <!-- no translation found for voice_warning_may_not_understand (5596289095878251072) --> + <skip /> + <!-- no translation found for voice_warning_how_to_turn_off (3190378129944934856) --> + <skip /> + <!-- no translation found for voice_hint_dialog_message (1420686286820661548) --> + <skip /> <string name="voice_listening" msgid="467518160751321844">"Ussa discurrer"</string> <string name="voice_working" msgid="6666937792815731889">"Operaziun en progress"</string> <string name="voice_initializing" msgid="661962047129906646"></string> @@ -201,7 +193,8 @@ <string name="voice_punctuation_hint" msgid="1611389463237317754">"\""<b>"Commentari:"</b>" Empruvai la proxima giada d\'agiuntar segns d\'interpuncziun sco \"\"punct\"\", \"\"comma\"\" u \"\"segn da dumonda\"\" cun cumonds vocals.\""</string> <string name="cancel" msgid="6830980399865683324">"Interrumper"</string> <string name="ok" msgid="7898366843681727667">"OK"</string> - <!-- outdated translation 2466640768843347841 --> <string name="voice_input" msgid="3583258583521397548">"Cumonds vocals"</string> + <!-- no translation found for voice_input (3583258583521397548) --> + <skip /> <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> <skip /> <!-- no translation found for voice_input_modes_symbols_keyboard (7203213240786084067) --> @@ -221,12 +214,12 @@ <string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string> <!-- no translation found for select_language (3693815588777926848) --> <skip /> - <!-- outdated translation 8058519710062071085 --> <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tippar danovamain per memorisar"</string> + <!-- no translation found for hint_add_to_dictionary (9006292060636342317) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Dicziunari disponibel"</string> <string name="prefs_enable_log" msgid="6620424505072963557">"Activar il feedback da l\'utilisader"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Gidai a meglierar quest editur da la metoda d\'endataziun cun trametter automaticamain datas statisticas davart l\'utilisaziun e rapports da collaps a Google."</string> - <!-- outdated translation 437433231038683666 --> <string name="keyboard_layout" msgid="8451164783510487501">"Design da la tastatura"</string> - <!-- no translation found for subtype_de_qwerty (3358900499589259491) --> + <!-- no translation found for keyboard_layout (8451164783510487501) --> <skip /> <!-- no translation found for subtype_en_GB (88170601942311355) --> <skip /> diff --git a/java/res/values-ro/donottranslate-more-keys.xml b/java/res/values-ro/donottranslate-more-keys.xml index d7e6a171d..44613cf85 100644 --- a/java/res/values-ro/donottranslate-more-keys.xml +++ b/java/res/values-ro/donottranslate-more-keys.xml @@ -18,8 +18,28 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ă,â,à,á,ä,æ,ã,å,ā</string> - <string name="more_keys_for_i">8,î,ï,ì,í,į,ī</string> - <string name="more_keys_for_s">ș,ß,ś,š</string> - <string name="more_keys_for_t">5,ț</string> + <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+00E6: "æ" LATIN SMALL LETTER AE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON --> + <string name="more_keys_for_a">â,ã,ă,à,á,ä,æ,å,ā</string> + <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">î,ï,ì,í,į,ī</string> + <!-- U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ș,ß,ś,š</string> + <!-- U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW --> + <string name="more_keys_for_t">ț</string> </resources> diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml index c1dea5431..2445075f9 100644 --- a/java/res/values-ro/strings.xml +++ b/java/res/values-ro/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Tastatură Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tastatură Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Setările tastaturii Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Opţiuni de introducere text"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Corecţie Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Verificator ortografic Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Verificator ortografic Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Setări de verificare ortografică"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Utiliz. datele de proxim."</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Utilizaţi un algor. de prox. similar tastat. pt. verif. ortograf."</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Verificare nume în agendă"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Verificatorul ortografic utilizează intrări din lista de contacte"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Sunet la apăsarea tastei"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Fereastră pop-up la apăsarea tastei"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Corectare text"</string> <string name="misc_category" msgid="6894192814868233453">"Alte opţiuni"</string> <string name="advanced_settings" msgid="362895144495591463">"Setări avansate"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Opţiuni pt. utiliz. experţi"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Opţiuni pentru experţi"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Înt. înch. pop-up esenţ."</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fără întârziere"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Afişaţi întotdeauna"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Afişaţi în modul Portret"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ascundeţi întotdeauna"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Afişaţi tasta setări"</string> <string name="auto_correction" msgid="4979925752001319458">"Autocorecţie"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Corectare automată cuvinte prin bară spaţiu/semne punctuaţie"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Dezactivată"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: salvat"</string> <string name="label_go_key" msgid="1635148082137219148">"OK"</string> <string name="label_next_key" msgid="362972844525672568">"Înainte"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Înapoi"</string> <string name="label_done_key" msgid="2441578748772529288">"Terminat"</string> <string name="label_send_key" msgid="2815056534433717444">"Trimiteţi"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nu a fost introdus text"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Tasta cu codul %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift activat"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock activat"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Tasta Shift este activată (apăsaţi pentru a o dezactiva)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Tasta Caps Lock este activată (apăsaţi pentru a o dezactiva)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboluri"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Litere"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Intrare vocală"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Faţă zâmbitoare"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Virgulă"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punct"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Paranteză închisă"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Paranteză deschisă"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Două puncte"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Punct şi virgulă"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Semn de exclamaţie"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Semn de întrebare"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Ghilimele duble"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Ghilimele simple"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punct"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Rădăcină pătrată"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Marcă comercială"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"În atenţia"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Stea"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Diez"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Puncte de suspensie"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Ghilimele duble de deschidere"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Tasta Shift a fost activată"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Tasta Caps Lock a fost activată"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Tasta Shift a fost dezactivată"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Modul Simboluri"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Modul Alfanumeric"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Modul Telefon"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Modul Telefon cu simboluri"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Intrare voce"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Intrarea vocală nu este acceptată în prezent pentru limba dvs., însă funcţionează în limba engleză."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Intrarea vocală utilizează funcţia Google de recunoaştere vocală. Se aplică "<a href="http://m.google.com/privacy">"Politica de confidenţialitate Google Mobil"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Activaţi feedback de la utilizatori"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Ajutaţi la îmbunătăţirea acestui instrument de editare a metodelor de introducere a textului trimiţând în mod automat la Google statistici de utilizare şi rapoarte de blocare."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Temă pentru tastatură"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Tastatură germană QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engleză (Marea Britanie)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engleză (S.U.A.)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modul Studiu privind utilizarea"</string> diff --git a/java/res/values-ru/donottranslate-more-keys.xml b/java/res/values-ru/donottranslate-more-keys.xml index f7e006e84..a1a22e5aa 100644 --- a/java/res/values-ru/donottranslate-more-keys.xml +++ b/java/res/values-ru/donottranslate-more-keys.xml @@ -18,7 +18,6 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_cyrillic_e">5,ё</string> - <string name="more_keys_for_cyrillic_soft_sign">ъ</string> - <string name="more_keys_for_cyrillic_ha">ъ</string> + <!-- U+0451: "ё" CYRILLIC SMALL LETTER IO --> + <string name="more_keys_for_cyrillic_ye">ё</string> </resources> diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 863c8a28c..0d3d21de0 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Клавиатура Android"</string> - <string name="english_ime_settings" msgid="6661589557206947774">"Настройки клавиатуры Android"</string> - <string name="english_ime_input_options" msgid="3909945612939668554">"Параметры ввода"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Исправления Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавиатура Android (AOSP)"</string> + <string name="english_ime_settings" msgid="6661589557206947774">"Клавиатура Android"</string> + <string name="english_ime_input_options" msgid="3909945612939668554">"Настройки"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Проверка правописания Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Проверка правописания Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Настройка проверки правописания"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Алгоритм близости клавиш"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Использовать алгоритм близости клавиш для проверки правописания"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Поиск контактов"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Обращаться к списку контактов при проверке правописания"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Виброотклик клавиш"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Звук клавиш"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Увеличение нажатых"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Исправление текста"</string> <string name="misc_category" msgid="6894192814868233453">"Другие варианты"</string> <string name="advanced_settings" msgid="362895144495591463">"Расширенные настройки"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Для опытных пользователей"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Для опытных пользователей"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Задержка закрытия"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без задержки"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"По умолчанию"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Всегда показывать"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Показать вертикально"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Всегда скрывать"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Кнопка настроек"</string> <string name="auto_correction" msgid="4979925752001319458">"Автоисправление"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Автоматическое исправление опечаток при вводе знака препинания или пробела"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Откл."</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: сохранено"</string> <string name="label_go_key" msgid="1635148082137219148">"Поиск"</string> <string name="label_next_key" msgid="362972844525672568">"Далее"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Пред."</string> <string name="label_done_key" msgid="2441578748772529288">"Готово"</string> <string name="label_send_key" msgid="2815056534433717444">"Отправить"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"АБВ"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введен"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавиши:%d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Клавиша верхнего регистра"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Верхний регистр включен"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Включена фиксация верхнего регистра"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Верхний регистр включен (нажмите, чтобы отключить)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock включен (нажмите, чтобы отключить)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Клавиша удаления"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Клавиша символов"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Буквы"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Голосовой ввод"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Смайлик"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Клавиша \"Ввод\""</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Запятая"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Точка"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Открывающая скобка"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Закрывающая скобка"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Двоеточие"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Точка с запятой"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Восклицательный знак"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Вопросительный знак"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Двойная кавычка"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Одинарные кавычки"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Точка"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратный корень"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Число \"пи\""</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Дельта"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Товарный знак"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Знак процента"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Пометить"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Английский фунт"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Многоточие"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нижние двойные кавычки"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Верхний регистр включен"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock включен"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Верхний регистр отключен"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Режим добавления символов"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Режим ввода текста"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Режим набора номера"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Режим телефонных символов"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Голосовой ввод"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"В настоящее время функция голосового ввода не поддерживает ваш язык, но вы можете пользоваться ей на английском."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Голосовой ввод использует алгоритмы распознавания речи Google. Действует "<a href="http://m.google.com/privacy">"политика конфиденциальности для мобильных устройств"</a>"."</string> @@ -144,9 +140,8 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Включить отправку сведений"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Помогите усовершенствовать редактор способа ввода, разрешив отправку статистики и отчетов о сбоях в Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Немецкая клавиатура QWERTY"</string> - <string name="subtype_en_GB" msgid="88170601942311355">"Английский (Великобритания)"</string> - <string name="subtype_en_US" msgid="6160452336634534239">"Английский (США)"</string> + <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string> + <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим проверки удобства использования"</string> <string name="prefs_keypress_vibration_duration_settings" msgid="1829950405285211668">"Настройки вибросигнала при нажатии клавиш"</string> <string name="prefs_keypress_sound_volume_settings" msgid="5875933757082305040">"Настройки громкости звука при нажатии клавиш"</string> diff --git a/java/res/values-sk/donottranslate-more-keys.xml b/java/res/values-sk/donottranslate-more-keys.xml index b73db0a46..f6e1e8d72 100644 --- a/java/res/values-sk/donottranslate-more-keys.xml +++ b/java/res/values-sk/donottranslate-more-keys.xml @@ -18,18 +18,90 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">ä,á,à,â,æ,ã,å,ā</string> - <string name="more_keys_for_e">3,é,ě,è,ê,ë,ę,ė,ē</string> - <string name="more_keys_for_i">8,í,î,ï,ì,į,ī</string> - <string name="more_keys_for_o">9,ô,ó,ö,ò,õ,œ,ø,ō</string> - <string name="more_keys_for_u">7,ú,ú,û,ü,ù,ū</string> - <string name="more_keys_for_s">š,ß,ś</string> - <string name="more_keys_for_n">ň,ñ,ń</string> - <string name="more_keys_for_c">č,ç,ć</string> - <string name="more_keys_for_y">6,ý,ÿ</string> - <string name="more_keys_for_d">ď</string> - <string name="more_keys_for_r">4,ŕ,ř</string> - <string name="more_keys_for_t">5,ť</string> - <string name="more_keys_for_z">ž,ź,ż</string> - <string name="more_keys_for_l">ľ,ĺ,ł</string> + <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS + U+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE + U+00E6: "æ" LATIN SMALL LETTER AE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK --> + <string name="more_keys_for_a">á,ä,ā,à,â,ã,å,æ,ą</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+011B: "ě" LATIN SMALL LETTER E WITH CARON + U+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK --> + <string name="more_keys_for_e">é,ě,ē,ė,è,ê,ë,ę</string> + <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+0131: "ı" LATIN SMALL LETTER DOTLESS I --> + <string name="more_keys_for_i">í,ī,į,ì,î,ï,ı</string> + <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+0153: "œ" LATIN SMALL LIGATURE OE + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_o">ô,ó,ö,ò,õ,œ,ő,ø</string> + <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE --> + <string name="more_keys_for_u">ú,ů,ü,ū,ų,ù,û,ű</string> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA --> + <string name="more_keys_for_s">š,ß,ś,ş</string> + <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON + U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE --> + <string name="more_keys_for_n">ň,ņ,ñ,ń,ń</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ç,ć</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS --> + <string name="more_keys_for_y">ý,ÿ</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON --> + <string name="more_keys_for_d">ď</string> + <!-- U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + U+0159: "ř" LATIN SMALL LETTER R WITH CARON + U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA --> + <string name="more_keys_for_r">ŕ,ř,ŗ</string> + <!-- U+0165: "ť" LATIN SMALL LETTER T WITH CARON + U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA --> + <string name="more_keys_for_t">ť,ţ</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE --> + <string name="more_keys_for_z">ž,ż,ź</string> + <!-- U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA --> + <string name="more_keys_for_k">ķ</string> + <!-- U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> + <string name="more_keys_for_l">ľ,ĺ,ļ,ł</string> + <!-- U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA + U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE --> + <string name="more_keys_for_g">ģ,ğ</string> </resources> diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml index b7ab8f204..91896d01c 100644 --- a/java/res/values-sk/strings.xml +++ b/java/res/values-sk/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Klávesnica Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Klávesnica Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Nastavenia klávesnice Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti zadávania textu a údajov"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Opravy pravopisu Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Kontrola pravopisu Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kontrola pravopisu Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavenia kontroly pravopisu"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Použiť údaje o blízkosti"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Na kontr. pravopis. použiť algor. vzdialenosti ako pri kláves."</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Vyhľadať kontakty"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kontrola pravopisu používa záznamy z vášho zoznamu kontaktov"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri stlačení klávesu"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Zobraziť znaky pri stlačení klávesu"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Oprava textu"</string> <string name="misc_category" msgid="6894192814868233453">"Ďalšie možnosti"</string> <string name="advanced_settings" msgid="362895144495591463">"Rozšírené nastavenia"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti pre skúsených používateľov"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti pre odborníkov"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Onesk. zrušenia kľúč. kon. okna"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez oneskorenia"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predvolená"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovať"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Zobraziť v režime na výšku"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývať"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Zobraziť kláves Nastavenia"</string> <string name="auto_correction" msgid="4979925752001319458">"Automatické opravy"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Stlačením medzerníka a interpunkcie sa aut. opravia chybné slová"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Vypnuté"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Uložené"</string> <string name="label_go_key" msgid="1635148082137219148">"Hľadať"</string> <string name="label_next_key" msgid="362972844525672568">"Ďalej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Pred."</string> <string name="label_done_key" msgid="2441578748772529288">"Hotovo"</string> <string name="label_send_key" msgid="2815056534433717444">"Odoslať"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Nie je zadaný žiadny text"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Kód klávesu %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Povolený kláves Shift"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Povolený kláves Caps Lock"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Kláves Shift je zapnutý (zakážete ho klepnutím)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Kláves Caps Lock je zapnutý (zakážete ho klepnutím)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboly"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Písmená"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Hlasový vstup"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Usmiata tvár"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Čiarka"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Bodka"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Ľavá zátvorka"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Pravá zátvorka"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dvojbodka"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Bodkočiarka"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Výkričník"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Otáznik"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Úvodzovky"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Jednoduché úvodzovky"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Bodka"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Odmocnina"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pí"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Percento"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Hviezdička"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Libra"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri bodky"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Dolné úvodzovky"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Kláves Shift je povolený"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Kláves Caps Lock je povolený"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Kláves Shift je zakázaný"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Režim symbolov"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Režim písmen"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Režim telefónu"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Režim telefónnych symbolov"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Hlasový vstup"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Pre váš jazyk aktuálne nie je hlasový vstup podporovaný, ale funguje v angličtine."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Hlasový vstup používa rozpoznávanie hlasu Google. Na používanie hlasového vstupu sa vzťahujú "<a href="http://m.google.com/privacy">"Pravidlá ochrany osobných údajov pre mobilné služby"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Povoliť spätnú väzbu od používateľov"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Automatickým zasielaním štatistík o využívaní editora metódy vstupu a správ o jeho zlyhaní do služby Google môžete prispieť k vylepšeniu tohto nástroja."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Motív klávesnice"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Nemecká klávesnica QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Anglická klávesnica (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Anglická klávesnica (US)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Režim štúdie použiteľnosti"</string> diff --git a/java/res/values-sl/donottranslate-more-keys.xml b/java/res/values-sl/donottranslate-more-keys.xml new file mode 100644 index 000000000..ccff2ac29 --- /dev/null +++ b/java/res/values-sl/donottranslate-more-keys.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">š</string> + <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE --> + <string name="more_keys_for_c">č,ć</string> + <!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE --> + <string name="more_keys_for_d">đ</string> + <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON --> + <string name="more_keys_for_z">ž</string> +</resources> diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml index d7f357aa0..88d29a9e6 100644 --- a/java/res/values-sl/strings.xml +++ b/java/res/values-sl/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Tipkovnica Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Tipkovnica Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Nastavitve tipkovnice Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Možnosti vnosa"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Preverjanje črkovanja za Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Črkovalnik za Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Črkovalnik za Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Nastavitve preverjanja črkovanja"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Uporabi podatke bližine"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Uporaba algoritma za preverjanje črkovanja na podlagi bližine znakov na tipkovnici"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Iskanje imen stikov"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Črkovalnik uporablja vnose s seznama stikov"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Zvok ob pritisku tipke"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Povečaj črko ob pritisku"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Popravljanje besedila"</string> <string name="misc_category" msgid="6894192814868233453">"Druge možnosti"</string> <string name="advanced_settings" msgid="362895144495591463">"Dodatne nastavitve"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Možnosti za izkušene uporabnike"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Možnosti za strokovnjake"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Trajanje povečanja tipke"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Brez zakasnitve"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vedno pokaži"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Pokaži v pokončnem načinu"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vedno skrij"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Tipka za prikaz nastavitev"</string> <string name="auto_correction" msgid="4979925752001319458">"Samodejni popravek"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Preslednica in ločila samodejno popravijo napačno vtipkane besede"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Izklopljeno"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: shranjeno"</string> <string name="label_go_key" msgid="1635148082137219148">"Pojdi"</string> <string name="label_next_key" msgid="362972844525672568">"Naprej"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Nazaj"</string> <string name="label_done_key" msgid="2441578748772529288">"Dokončano"</string> <string name="label_send_key" msgid="2815056534433717444">"Pošlji"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Ni vnesenega besedila"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Koda tipke %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Tipka »Shift« je omogočena"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Funkcija »Caps Lock« je omogočena"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift je vklopljen (dotaknite se, da onemogočite)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock je vklopljen (dotaknite se, da onemogočite)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simboli"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Pisma"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Glasovni vnos"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smeško"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Vračalka"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Vejica"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Pika"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Levi oklepaj"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Desni oklepaj"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dvopičje"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Podpičje"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Klicaj"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Vprašaj"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dvojni narekovaji"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enojni narekovaj"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Pika"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Koren"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Blagovna znamka"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Odstotek"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Zvezdica"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Lojtra"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Tri pike"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Spodnji dvojni narekovaji"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Način »Shift« je omogočen"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Način »Caps Lock« je omogočen"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Način »Shift« je onemogočen"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Način simbolov"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Način črk"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Način telefona"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Način simbolov telefona"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Glasovni vnos"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Glasovni vnos trenutno ni podprt v vašem jeziku, deluje pa v angleščini."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Glasovni vnos uporablja Googlovo prepoznavanje govora. Zanj velja "<a href="http://m.google.com/privacy">"pravilnik o zasebnosti za mobilne naprave"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Omogoči povratne informacije uporabnikov"</string> <string name="prefs_description_log" msgid="5827825607258246003">"S samodejnim pošiljanjem statističnih podatkov o uporabi in poročil o zrušitvah Googlu nam lahko pomagate izboljšati urejevalnik načina vnosa."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Nemška QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"angleščina (Združeno kraljestvo)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"angleščina (ZDA)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Način za preučevanje uporabnosti"</string> diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml index 0906fce6e..463165b6f 100644 --- a/java/res/values-sr/strings.xml +++ b/java/res/values-sr/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android тастатура"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android тастатура (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Подешавања Android тастатуре"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Опције уноса"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android исправљање"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android провера правописа"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android провера правописа (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Подешавања провере правописа"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Употреба података близине"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Употреба алгоритма близине попут тастатуре за проверу правописа"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Потражи имена контаката"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Контролор правописа користи уносе са листе контаката"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вибрирај на притисак тастера"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Звук на притисак тастера"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Искачући прозор приликом притиска тастера"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Исправљање текста"</string> <string name="misc_category" msgid="6894192814868233453">"Друге опције"</string> <string name="advanced_settings" msgid="362895144495591463">"Напредна подешавања"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Опције за искусне кориснике"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Опције за стручњаке"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Одложи одбац. иск. прозора тастера"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без одлагања"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Подразумевано"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Увек прикажи"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Прикажи у усправном режиму"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Увек сакриј"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Прикажи тастер за подешавања"</string> <string name="auto_correction" msgid="4979925752001319458">"Аутоматско исправљање"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Размак и интерпункција аутоматски исправљају грешке у куцању"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Искључи"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Сачувано"</string> <string name="label_go_key" msgid="1635148082137219148">"Иди"</string> <string name="label_next_key" msgid="362972844525672568">"Следеће"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Прет."</string> <string name="label_done_key" msgid="2441578748772529288">"Готово"</string> <string name="label_send_key" msgid="2815056534433717444">"Пошаљи"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст није унет"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Кôд тастера %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Тастер Shift је омогућен"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock је омогућен"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift је укључен (додирните да бисте га онемогућили)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock је укључен (додирните да бисте га онемогућили)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Симболи"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Слова"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Гласовни унос"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Смајли"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Зарез"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Тачка"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Лева заграда"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Десна заграда"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Две тачке"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Тачка-зарез"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Знак узвика"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Знак питања"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Дупли наводник"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Полунаводник"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Тачка"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратни корен"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Пи"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Делта"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Жиг"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"За"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Звездица"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Фунта"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Три тачке"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Отворени доњи наводници"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift је омогућен"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock је омогућен"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift је онемогућен"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Режим симбола"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Режим слова"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Режим телефона"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Режим симбола телефона"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Гласовни унос"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Гласовни унос тренутно није подржан за ваш језик, али функционише на енглеском."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Гласовни унос користи Google-ову функцију за препознавање гласа. Примењује се "<a href="http://m.google.com/privacy">"политика приватности за мобилне уређаје"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Омогући повратну информацију корисника"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Помозите да се побољша овај уређивач режима уноса тако што ће се аутоматски послати статистика о коришћењу и извештаји о грешкама компанији Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Тема тастатуре"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY тастатура за немачки"</string> <string name="subtype_en_GB" msgid="88170601942311355">"енглески (УК)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим за студију могућности коришћења"</string> diff --git a/java/res/values-sv/donottranslate-more-keys.xml b/java/res/values-sv/donottranslate-more-keys.xml index 1fa29a83e..e3662df69 100644 --- a/java/res/values-sv/donottranslate-more-keys.xml +++ b/java/res/values-sv/donottranslate-more-keys.xml @@ -18,12 +18,37 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_e">3,é,è,ê,ë,ę</string> - <string name="more_keys_for_o">9,œ,ô,ò,ó,õ,ō</string> - <string name="more_keys_for_u">7,ü,û,ù,ú,ū</string> - <string name="more_keys_for_s">ß,ś,š</string> - <string name="keylabel_for_scandinavia_row2_10">ö</string> - <string name="keylabel_for_scandinavia_row2_11">ä</string> - <string name="more_keys_for_scandinavia_row2_10">ø</string> - <string name="more_keys_for_scandinavia_row2_11">æ</string> + <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK --> + <string name="more_keys_for_e">é,è,ê,ë,ę</string> + <!-- U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">œ,ô,ò,ó,õ,ō</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ü,û,ù,ú,ū</string> + <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ß,ś,š</string> + <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE --> + <string name="keylabel_for_scandinavia_row1_11">å</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_scandinavia_row2_11">ä</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_scandinavia_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="more_keys_for_scandinavia_row2_11">æ</string> </resources> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 46760bbe2..992604a41 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Androids tangentbord"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Androids tangentbord (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Inställningar för Androids tangentbord"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Inmatningsalternativ"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android-korrigering"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Stavningskontroll i Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Stavningskontroll i Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Inställningar för stavningskontroll"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Använd närhetsinformation"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Använd tangentbordsliknande närhetsalgoritm för stavningskontroll"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Sök namn på kontakter"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"I stavningskontrollen används poster från kontaktlistan"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Knappljud"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Popup vid knapptryck"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Textkorrigering"</string> <string name="misc_category" msgid="6894192814868233453">"Andra alternativ"</string> <string name="advanced_settings" msgid="362895144495591463">"Avancerade inställningar"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Alternativ för expertanvändare"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Alternativ för experter"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ta bort popup-fördröjning"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fördröj inte"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visa alltid"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Visa stående"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Dölj alltid"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Visa inställningsknapp"</string> <string name="auto_correction" msgid="4979925752001319458">"Autokorrigering"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Blanksteg/skiljetecken rättar felstavning"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Av"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>: sparat"</string> <string name="label_go_key" msgid="1635148082137219148">"Kör"</string> <string name="label_next_key" msgid="362972844525672568">"Nästa"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Föreg"</string> <string name="label_done_key" msgid="2441578748772529288">"Färdig"</string> <string name="label_send_key" msgid="2815056534433717444">"Skicka"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Ingen text har angetts"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Nyckelkod %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Skift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Skift aktiverat"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock är aktiverat"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Skift på (knacka lätt för att inaktivera)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock på (knacka lätt för att inaktivera)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Symboler"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Bokstäver"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Röstinmatning"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Uttryckssymbol"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Retur"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Komma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Punkt"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Vänster parentes"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Högerparentes"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Kolon"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikolon"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Utropstecken"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Frågetecken"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dubbla citattecken"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Enkla citattecken"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Punkt"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Kvadratrot"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Stjärna"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Fyrkant"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellips"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Nedre dubbla citattecken"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Skift är aktiverat"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock är aktiverat"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Skift är inaktiverat"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Symbolläge"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Bokstavsläge"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefonläge"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefonsymbolläge"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Röstindata"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Röstindata stöds inte på ditt språk än, men tjänsten fungerar på engelska."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Röstinmatning använder sig av Googles tjänst för taligenkänning. "<a href="http://m.google.com/privacy">"Sekretesspolicyn för mobila enheter"</a>" gäller."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Aktivera synpunkter från användare"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Du kan hjälpa till att förbättra inmatningsmetoden genom att automatiskt skicka användningsstatistik och felrapporter till Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tangentbordstema"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Tyskt QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Engelskt (brittiskt)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Engelskt (amerikanskt)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Läge för studie av användbarhet"</string> diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml index 822907b05..12185cacb 100644 --- a/java/res/values-sw/strings.xml +++ b/java/res/values-sw/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Kibodi ya Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Kicharazio cha Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Mipangilio ya kibodi ya Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Chaguo za uingizaji"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Masahihisho ya Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Kikagua tahajia cha Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Kikagua tahajia cha Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Mipangilio ya kukagua sarufi"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Tumia data ya ukaribu"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Tumia kibodi kama ukaribu wa algorithmu kwa ukaguzi wa sarufi"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Angalia majina ya wasiliani"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Kikagua tahajia hutumia ingizo kutoka kwa orodha yako ya anwani"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Ibuka kitufe kinapobonyezwa"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Marekebisho ya maandishi"</string> <string name="misc_category" msgid="6894192814868233453">"Chaguo zingine"</string> <string name="advanced_settings" msgid="362895144495591463">"Mipangilio mahiri"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Machaguo ya watumiaji wataalamu"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Chaguo za wataalamu"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Kuchelewesha kutupa kitufe ibukizi"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Hakuna kuchelewa"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Onyesha kila wakati"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Onyesha kwenye hali wima"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ficha kila wakati"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Onyesha kitufe cha mipangilio"</string> <string name="auto_correction" msgid="4979925752001319458">"Usahihishaji Kioto"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Kiaamba na kiakifishi hurekebisha maneno ambayo yamechapishwa vibaya"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Zima"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Imehifadhiwa"</string> <string name="label_go_key" msgid="1635148082137219148">"Nenda"</string> <string name="label_next_key" msgid="362972844525672568">"Ifuatayo"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Iliyotangulia"</string> <string name="label_done_key" msgid="2441578748772529288">"Kwisha"</string> <string name="label_send_key" msgid="2815056534433717444">"Tuma"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Hakuna maandishi yaliyoingizwa"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Msimbo wa kitufe %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Badilisha"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Kuhamisha kumewezeshwa"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Herufi kubwa imewezeshwa"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift imewashwa (gonga ili kulemaza)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock imewashwa (gonga ili kulemaza)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Futa"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Alama"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Herufi"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Uingizaji sauti"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Uso wenye tabasamu"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Rudi"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Koma"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Muda"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Mabano ya kushoto"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"mabano ya kulia"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Nukta mbili juu na chini"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Semikoloni"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Alama ya mshangao"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Alama ya kiulizio"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Nukuu mara mbili"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Nukuu moja"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Nukta"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Chapa ya Biashara"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Kwa ulinzi wa"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Nyota"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pauni"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Nukuu ya chini maradufu"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift imewezeshwa"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps lock imewezeshwa"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift imelemazwa"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Hali ya alama"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Hali ya barua"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Hali ya simu"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Hali ya alama za simu"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Uingizaji wa sauti"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Uingizaji wa sauti hauhimiliwi kwa lugha yako kwa sasa, lakini inafanya kazi kwa Kiingereza."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Uingizaji wa sauti hutumia utambuaji wa usemi wa Google. "<a href="http://m.google.com/privacy">"Sera ya Faragha ya Simu za mkononi "</a>" hutumika."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Wezesha maoni ya watumiaji"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Saidia kuimarisha mbinu ya uingizaji wa kihariri, kwa kutuma takwimu za matumizi na ripoti za kuvurugika kwa Google kiotomatiki."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Maandhari ya kibodi"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY ya Kijerumani"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Kiingereza cha (Uingereza)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Kiingereza cha (Marekani)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Modi ya uchunguzi wa utumizi"</string> diff --git a/java/res/values-sw600dp-land/dimens.xml b/java/res/values-sw600dp-land/dimens.xml index 1b8c8a64a..68083b534 100644 --- a/java/res/values-sw600dp-land/dimens.xml +++ b/java/res/values-sw600dp-land/dimens.xml @@ -48,10 +48,9 @@ <fraction name="key_hint_letter_ratio">23%</fraction> <fraction name="key_hint_label_ratio">34%</fraction> <fraction name="key_uppercase_letter_ratio">29%</fraction> + <fraction name="spacebar_text_ratio">33.33%</fraction> <dimen name="suggestions_strip_padding">40.0mm</dimen> <integer name="max_more_suggestions_row">5</integer> <fraction name="min_more_suggestions_width">50%</fraction> - <!-- key_preview_backing_height = more_suggestions_row_height * max_more_suggestions_row --> - <dimen name="key_preview_backing_height">220dip</dimen> </resources> diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml index 1854a8696..c507bd2a9 100644 --- a/java/res/values-sw600dp/config.xml +++ b/java/res/values-sw600dp/config.xml @@ -19,25 +19,25 @@ --> <resources> - <bool name="config_enable_show_settings_key_option">true</bool> - <bool name="config_default_show_settings_key">false</bool> <bool name="config_enable_show_voice_key_option">false</bool> <bool name="config_enable_show_popup_on_keypress_option">false</bool> <bool name="config_enable_bigram_suggestions_option">false</bool> - <bool name="config_sliding_key_input_enabled">false</bool> - <bool name="config_digit_more_keys_enabled">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">false</bool> <bool name="config_default_sound_enabled">true</bool> <bool name="config_auto_correction_spacebar_led_enabled">false</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">true</bool> <!-- The language is never displayed if == 0, always displayed if < 0 --> <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> <integer name="config_long_press_space_key_timeout">0</integer> <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> - <string name="config_default_keyboard_theme_id" translatable="false">5</string> - <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string> + <string name="config_default_keyboard_theme_index" translatable="false">5</string> <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for LatinKeyboardView + --> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool> </resources> diff --git a/java/res/values-sw600dp/dimens.xml b/java/res/values-sw600dp/dimens.xml index 31830239d..a86102421 100644 --- a/java/res/values-sw600dp/dimens.xml +++ b/java/res/values-sw600dp/dimens.xml @@ -40,12 +40,12 @@ <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <dimen name="mini_keyboard_key_horizontal_padding">6dip</dimen> + <dimen name="more_keys_keyboard_key_horizontal_padding">6dip</dimen> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> <!-- popup_key_height x 1.2 --> - <dimen name="mini_keyboard_slide_allowance">15.6mm</dimen> + <dimen name="more_keys_keyboard_slide_allowance">15.6mm</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-13.0mm</dimen> <!-- left or right padding of label alignment --> <dimen name="key_label_horizontal_padding">6dip</dimen> @@ -59,18 +59,19 @@ <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">26%</fraction> <fraction name="key_preview_text_ratio">50%</fraction> + <fraction name="spacebar_text_ratio">32.14%</fraction> <dimen name="key_preview_height">15.0mm</dimen> <dimen name="key_preview_offset">0.1in</dimen> <dimen name="key_preview_height_ics">15.0mm</dimen> <dimen name="key_preview_offset_ics">0.05in</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-5mm</dimen> <dimen name="suggestions_strip_height">44dip</dimen> <dimen name="more_suggestions_row_height">44dip</dimen> <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> - <!-- key_preview_backing_height = more_suggestions_row_height * max_more_suggestions_row --> - <dimen name="key_preview_backing_height">264dip</dimen> <dimen name="suggestions_strip_padding">15.0mm</dimen> <dimen name="suggestion_min_width">0.3in</dimen> <dimen name="suggestion_padding">12dip</dimen> diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml index 664e8c159..ef39f4393 100644 --- a/java/res/values-sw768dp-land/dimens.xml +++ b/java/res/values-sw768dp-land/dimens.xml @@ -52,6 +52,7 @@ <fraction name="key_hint_letter_ratio">23%</fraction> <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">24%</fraction> + <fraction name="spacebar_text_ratio">24.00%</fraction> <dimen name="key_preview_height">17.0mm</dimen> <dimen name="key_preview_height_ics">26.5mm</dimen> diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml index c25139a42..b78a6c62a 100644 --- a/java/res/values-sw768dp/config.xml +++ b/java/res/values-sw768dp/config.xml @@ -19,25 +19,25 @@ --> <resources> - <bool name="config_enable_show_settings_key_option">false</bool> - <bool name="config_default_show_settings_key">true</bool> <bool name="config_enable_show_voice_key_option">false</bool> <bool name="config_enable_show_popup_on_keypress_option">false</bool> <bool name="config_enable_bigram_suggestions_option">false</bool> - <bool name="config_sliding_key_input_enabled">false</bool> - <bool name="config_digit_more_keys_enabled">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">false</bool> <bool name="config_default_sound_enabled">true</bool> <bool name="config_auto_correction_spacebar_led_enabled">false</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">true</bool> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> <integer name="config_long_press_space_key_timeout">0</integer> <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> - <string name="config_default_keyboard_theme_id" translatable="false">5</string> - <string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string> + <string name="config_default_keyboard_theme_index" translatable="false">5</string> <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for LatinKeyboardView + --> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">true</bool> <!-- Screen metrics for logging. 0 = "mdpi phone screen" 1 = "hdpi phone screen" diff --git a/java/res/values-sw768dp/dimens.xml b/java/res/values-sw768dp/dimens.xml index bb4937dd5..a9ad030fe 100644 --- a/java/res/values-sw768dp/dimens.xml +++ b/java/res/values-sw768dp/dimens.xml @@ -43,12 +43,12 @@ <dimen name="popup_key_height">10.0mm</dimen> - <dimen name="mini_keyboard_key_horizontal_padding">12dip</dimen> + <dimen name="more_keys_keyboard_key_horizontal_padding">12dip</dimen> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> <!-- popup_key_height x 1.2 --> - <dimen name="mini_keyboard_slide_allowance">15.6mm</dimen> + <dimen name="more_keys_keyboard_slide_allowance">15.6mm</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-13.0mm</dimen> <!-- left or right padding of label alignment --> <dimen name="key_label_horizontal_padding">6dip</dimen> @@ -62,18 +62,19 @@ <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">26%</fraction> <fraction name="key_preview_text_ratio">50%</fraction> + <fraction name="spacebar_text_ratio">29.03%</fraction> <dimen name="key_preview_height">15.0mm</dimen> <dimen name="key_preview_offset">0.1in</dimen> <dimen name="key_preview_height_ics">15.0mm</dimen> <dimen name="key_preview_offset_ics">0.05in</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-5mm</dimen> <dimen name="suggestions_strip_height">44dip</dimen> <dimen name="more_suggestions_row_height">44dip</dimen> <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> - <!-- key_preview_backing_height = more_suggestions_row_height * max_more_suggestions_row --> - <dimen name="key_preview_backing_height">264dip</dimen> <dimen name="suggestions_strip_padding">15.0mm</dimen> <dimen name="suggestion_min_width">46dip</dimen> <dimen name="suggestion_padding">8dip</dimen> diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml index 53f56606c..f291fcce7 100644 --- a/java/res/values-th/strings.xml +++ b/java/res/values-th/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"แป้นพิมพ์ Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"การตั้งค่าแป้นพิมพ์ Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"ตัวเลือกการป้อนข้อมูล"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"การแก้ไขของ Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"แอนดรอยด์ตรวจสอบการสะกด"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"แอนดรอยด์ตรวจสอบการสะกด (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"การตั้งค่าการตรวจสอบการสะกด"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"ใช้ข้อมูลที่ใกล้เคียง"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"ใช้อัลกอริทึมใกล้เคียงที่คล้ายกับแป้นพิมพ์สำหรับตรวจสอบการสะกด"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"ค้นหารายชื่อติดต่อ"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"เครื่องมือตรวจการสะกดใช้รายการจากรายชื่อติดต่อของคุณ"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"สั่นเมื่อกดปุ่ม"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"ส่งเสียงเมื่อกดปุ่ม"</string> <string name="popup_on_keypress" msgid="123894815723512944">"ป๊อปอัปเมื่อกดแป้น"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"การแก้ไขข้อความ"</string> <string name="misc_category" msgid="6894192814868233453">"ตัวเลือกอื่นๆ"</string> <string name="advanced_settings" msgid="362895144495591463">"การตั้งค่าขั้นสูง"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"ตัวเลือกสำหรับผู้ใช้ที่มีความเชี่ยวชาญ"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"ตัวเลือกสำหรับผู้เชี่ยวชาญ"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"หน่วงเวลาก่อนปิดป๊อปอัพหลัก"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"ไม่มีการหน่วงเวลา"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"ค่าเริ่มต้น"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"แสดงทุกครั้ง"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"แสดงในโหมดแนวตั้ง"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"ซ่อนทุกครั้ง"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"แสดงแป้นการตั้งค่า"</string> <string name="auto_correction" msgid="4979925752001319458">"การแก้ไขอัตโนมัติ"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"กดเว้นวรรคและเครื่องหมายจะแก้คำผิดอัตโนมัติ"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"ปิด"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : บันทึกแล้ว"</string> <string name="label_go_key" msgid="1635148082137219148">"ไป"</string> <string name="label_next_key" msgid="362972844525672568">"ถัดไป"</string> + <string name="label_previous_key" msgid="1211868118071386787">"ก่อนหน้า"</string> <string name="label_done_key" msgid="2441578748772529288">"เสร็จสิ้น"</string> <string name="label_send_key" msgid="2815056534433717444">"ส่ง"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"ไม่มีข้อความ"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"รหัสคีย์ %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"เปิดใช้งาน Shift แล้ว"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"เปิดใช้งาน Caps Lock แล้ว"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift เปิดอยู่ (แตะเพื่อปิดใช้งาน)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock เปิดอยู่ (แตะเพื่อปิดใช้งาน)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"ลบ"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"สัญลักษณ์"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"ตัวอักษร"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"การป้อนข้อมูลด้วยเสียง"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"หน้ายิ้ม"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"เครื่องหมายจุลภาค"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"มหัพภาค"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"วงเล็บซ้าย"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"วงเล็บขวา"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"เครื่องหมายจุดคู่"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"อัฒภาค"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"อัศเจรีย์"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"เครื่องหมายคำถาม"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"อัญประกาศ"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"เครื่องหมายคำพูดเดี่ยว"</string> <string name="spoken_description_dot" msgid="40711082435231673">"เครื่องหมายจุด"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"รากที่สอง"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"เดลตา"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"เครื่องหมายการค้า"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"ติดดาว"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"ปอนด์"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"จุดไข่ปลา"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"อัญประกาศล่าง"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"เปิดใช้งาน Shift แล้ว"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"เปิดใช้งาน Caps Lock แล้ว"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"ปิดใช้งาน Shift แล้ว"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"โหมดสัญลักษณ์"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"โหมดตัวอักษร"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"โหมดโทรศัพท์"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"โหมดสัญลักษณ์โทรศัพท์"</string> <string name="voice_warning_title" msgid="4419354150908395008">"การป้อนข้อมูลด้วยเสียง"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"ขณะนี้การป้อนข้อมูลด้วยเสียงยังไม่ได้รับการสนับสนุนในภาษาของคุณ แต่ใช้ได้ในภาษาอังกฤษ"</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"ป้อนข้อมูลด้วยเสียงใช้การจดจำคำพูดของ Google "<a href="http://m.google.com/privacy">" นโยบายส่วนบุคคลของมือถือ"</a>"มีผลบังคับใช้"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"เปิดใช้งานการแสดงความคิดเห็นจากผู้ใช้"</string> <string name="prefs_description_log" msgid="5827825607258246003">"ช่วยปรับปรุงตัวแก้ไขวิธีการป้อนข้อมูลนี้โดยการส่งสถิติการใช้งานและรายงานการขัดข้องถึง Google โดยอัตโนมัติ"</string> <string name="keyboard_layout" msgid="8451164783510487501">"ชุดรูปแบบแป้นพิมพ์"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"QWERTY ภาษาเยอรมัน"</string> <string name="subtype_en_GB" msgid="88170601942311355">"อังกฤษ (สหราชอาณาจักร)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"อังกฤษ (อเมริกัน)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"โหมดศึกษาประโยชน์ในการใช้งาน"</string> diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml index 701963f2a..53ae616f1 100644 --- a/java/res/values-tl/strings.xml +++ b/java/res/values-tl/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android keyboard"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android keyboard (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Mga setting ng Android keyboard"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Mga pagpipilian sa input"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Pagwawasto sa Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Pang-check ng pagbabaybay ng Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Pang-check ng pagbabaybay ng Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Mga setting ng pang-check ng pagbabaybay"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Gamitin ang proximity data"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Gumamit ng proximity algorithm na tulad ng keyboard para sa pag-check ng pagbabaybay"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Maghanap pangalan contact"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Gumagamit pang-check pagbabaybay entry sa iyong listahan contact"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Tunog sa keypress"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Popup sa keypress"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Pagwawasto ng teksto"</string> <string name="misc_category" msgid="6894192814868233453">"Iba pang mga pagpipilian"</string> <string name="advanced_settings" msgid="362895144495591463">"Mga advanced na setting"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Mga pagpipilian para sa mga ekspertong user"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Mga pagpipilian para sa mga dalubhasa"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Balewala antala key popup"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Walang antala"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Palaging ipakita"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Ipakita sa portrait mode"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Palaging itago"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Ipakita ang key ng mga setting"</string> <string name="auto_correction" msgid="4979925752001319458">"Awtomatikong pagwasto"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Awto tinatama ng spacebar at bantas ang maling na-type"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Naka-off"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Na-save"</string> <string name="label_go_key" msgid="1635148082137219148">"Punta"</string> <string name="label_next_key" msgid="362972844525672568">"Susunod"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Nkrn"</string> <string name="label_done_key" msgid="2441578748772529288">"Tapos na"</string> <string name="label_send_key" msgid="2815056534433717444">"Ipadala"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Walang tekstong inilagay"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Code ng key %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Pinagana ang shift"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Pinagana ang caps lock"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Naka-on ang shift (i-tap upang huwag paganahin)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Naka-on ang caps lock (i-tap upang huwag paganahin)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Tanggalin"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Mga Simbolo"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Mga Titik"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Input ng boses"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Smiley na mukha"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Bumalik"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Kuwit"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Tuldok"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Kaliwang panaklong"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Kanang panaklong"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Tutuldok"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Tuldukuwit"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Tandang padamdam"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Tandang pananong"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Panipi"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Kudlit"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Tuldok"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Square root"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Trademark"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Care of"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Star"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Pound"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Mababang panipi"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Pinagana ang shift"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Pinagana ang caps lock"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Hindi pinagana ang shift"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Mode ng mga simbolo"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Mode ng mga titik"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Mode ng telepono"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Mode ng mga simbolo ng telepono"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Pag-input ng boses"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Hindi kasalukuyang suportado ang pag-input ng boses para sa iyong wika, ngunit gumagana sa Ingles."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Gumagamit ang pag-input ng boses ng speech recognition ng Google. Nalalapat "<a href="http://m.google.com/privacy">"Ang Patakaran sa Privacy ng Mobile"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Paganahin ang feedback ng user"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Tumulong na pahusayin ang editor ng paraan ng pag-input na ito sa pamamagitan ng awtomatikong pagpapadala ng mga istatistika ng paggamit at mga ulat ng crash sa Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Tema ng keyboard"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"German na QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Ingles (UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Ingles (Estados Unidos)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Study mode ng pagiging kapaki-pakinabang"</string> diff --git a/java/res/values-tr/donottranslate-more-keys.xml b/java/res/values-tr/donottranslate-more-keys.xml index 6906b3580..1161811d4 100644 --- a/java/res/values-tr/donottranslate-more-keys.xml +++ b/java/res/values-tr/donottranslate-more-keys.xml @@ -18,11 +18,40 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">â</string> - <string name="more_keys_for_i">8,ı,î,ï,ì,í,į,ī</string> - <string name="more_keys_for_o">9,ö,ô,œ,ò,ó,õ,ø,ō</string> - <string name="more_keys_for_u">7,ü,û,ù,ú,ū</string> - <string name="more_keys_for_s">ş,ß,ś,š</string> - <string name="more_keys_for_g">ğ</string> - <string name="more_keys_for_c">ç,ć,č</string> + <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX --> + <string name="more_keys_for_a">â</string> + <!-- U+0131: "ı" LATIN SMALL LETTER DOTLESS I + U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON --> + <string name="more_keys_for_i">ı,î,ï,ì,í,į,ī</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+0153: "œ" LATIN SMALL LIGATURE OE + U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON --> + <string name="more_keys_for_o">ö,ô,œ,ò,ó,õ,ø,ō</string> + <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS + U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX + U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON --> + <string name="more_keys_for_u">ü,û,ù,ú,ū</string> + <!-- U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+0161: "š" LATIN SMALL LETTER S WITH CARON --> + <string name="more_keys_for_s">ş,ß,ś,š</string> + <!-- U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE --> + <string name="more_keys_for_g">ğ</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ç,ć,č</string> </resources> diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 4ae7d78c9..01acfbf60 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android klavyesi"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android klavye (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android klavye ayarları"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Giriş seçenekleri"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android düzeltme"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android yazım denetleyici"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android yazım denetleyici (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Yazım denetimi ayarları"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Yakınlık verilri kullan"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Yazım denetimi içn klavye benzeri yakınlık algoritması kullan"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kişi adlarını denetle"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Yazım denetleyici, kişi listenizdeki girişleri kullanır"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Tuşa basıldığında ses çıkar"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Tuşa basıldığında pop-up aç"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Metin düzeltme"</string> <string name="misc_category" msgid="6894192814868233453">"Diğer seçenekler"</string> <string name="advanced_settings" msgid="362895144495591463">"Gelişmiş ayarlar"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Uzman kullanıcılar için seçenekler"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Uzmanlar için seçenekler"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tuş popup içn kaptm ertlm"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Gecikme yok"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Her zaman göster"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Dikey modda göster"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Her zaman gizle"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Ayarları göster tuşu"</string> <string name="auto_correction" msgid="4979925752001319458">"Otomatik düzeltme"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Boşluk çbğ ve nokt işr yanlış yazılan kelimeleri oto düzeltir"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Kapalı"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kaydedildi"</string> <string name="label_go_key" msgid="1635148082137219148">"Git"</string> <string name="label_next_key" msgid="362972844525672568">"İleri"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Önceki"</string> <string name="label_done_key" msgid="2441578748772529288">"Bitti"</string> <string name="label_send_key" msgid="2815056534433717444">"Gönder"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Hiç metin girilmedi"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Tuş kodu: %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Üst Karakter"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Üst Karakter Etkin"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Büyük harf etkin"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Üst karakter açık (devre dışı bırakmak için hafifçe vurun)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Büyük harf kilidi açık (devre dışı bırakmak içinn hafifçe vurun)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Simgeler"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Harfler"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Ses girişi"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Gülen yüz"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Enter"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Virgül"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Nokta"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Sol parantez"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Sağ parantez"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"İki Nokta"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Noktalı virgül"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Ünlem işareti"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Soru işareti"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Çift tırnak"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Tek tırnak işareti"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Nokta"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Karekök"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Ticari marka"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Yüzde işareti"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Yıldız"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Kare"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Üç nokta"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Alt çift tırnak"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Üst karakter etkin"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Büyük harf kilidi etkin"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Üst karakter devre dışı"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Sembol modu"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Harf modu"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Telefon modu"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Telefon sembolleri modu"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Ses girişi"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Ses girişi, şu anda sizin diliniz için desteklenmiyor ama İngilizce dilinde kullanılabilir."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Ses girişi Google\'ın konuşma tanıma işlevini kullanır. "<a href="http://m.google.com/privacy">" Mobil Gizlilik Politikası"</a>" geçerlidir."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Kullanıcı geri bildirimini etkinleştir"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Kullanım istatistiklerini ve kilitlenme raporlarını Google\'a otomatik olarak göndererek bu giriş yöntemi düzenleyicisinin iyileştirilmesine yardımcı olun."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Klavye teması"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Almanca QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"İngilizce (BK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"İngilizce (ABD)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Kullanılabilirlik çalışması modu"</string> diff --git a/java/res/values-fr-rCA/donottranslate-more-keys.xml b/java/res/values-uk/donottranslate-more-keys.xml index 80e9d9346..323eaafbb 100644 --- a/java/res/values-fr-rCA/donottranslate-more-keys.xml +++ b/java/res/values-uk/donottranslate-more-keys.xml @@ -18,8 +18,8 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_a">à,â,æ,á,ä,ã,å,ā,ª</string> - <string name="more_keys_for_q">1</string> - <string name="more_keys_for_w">2</string> - <string name="more_keys_for_z"></string> + <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I --> + <string name="keylabel_for_cyrillic_yery">і</string> + <!-- U+0457: "ї" CYRILLIC SMALL LETTER YI --> + <string name="more_keys_for_cyrillic_yery">ї</string> </resources> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index 234a9c56a..ea970fe04 100644 --- a/java/res/values-uk/strings.xml +++ b/java/res/values-uk/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Клавіатура Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Клавіатура Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Налашт-ня клавіат. Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Парам. введення"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Виправлення Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Засіб перевірки орфографії Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Засіб перевірки орфографії Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Налаштування перевірки орфографії"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Використ. дані близькості"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Для перевірки орфогр. викор. алгоритм близьк., аналог. клавіат."</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Шукати імена контактів"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Програма перевірки правопису використ. записи зі списку контактів"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр при натиску клав."</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натиску клав."</string> <string name="popup_on_keypress" msgid="123894815723512944">"Сплив. при нат.клав."</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Виправлення тексту"</string> <string name="misc_category" msgid="6894192814868233453">"Інші опції"</string> <string name="advanced_settings" msgid="362895144495591463">"Розширені налаштування"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Налаштування для досвідчених користувачів"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Налаштування для досвідчених користувачів"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Затримка клавіши закриття"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Без затримки"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"За умовчанням"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Завжди показувати"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Показувати в книжковому режимі"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Завжди ховати"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Показ. клав. налашт."</string> <string name="auto_correction" msgid="4979925752001319458">"Автомат. виправлення"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Пробіл і пунктуація автоматично виправляють слова з помилками"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Вимк."</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : збережено"</string> <string name="label_go_key" msgid="1635148082137219148">"Іти"</string> <string name="label_next_key" msgid="362972844525672568">"Далі"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Назад"</string> <string name="label_done_key" msgid="2441578748772529288">"Готово"</string> <string name="label_send_key" msgid="2815056534433717444">"Надісл."</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"Алфавіт"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Текст не введено"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Код клавіші – %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Клавіша Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift увімкнено"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps Lock увімкнено"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift увімкнено (швидко торкніться, щоб вимкнути)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps Lock увімкнено (швидко торкніться, щоб вимкнути)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Клавіша Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Символи"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Літери"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Голосовий ввід"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Смайлик"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Клавіша Return"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Кома"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Крапка"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Ліва дужка"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Права дужка"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Двокрапка"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Крапка з комою"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Знак оклику"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Знак питання"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Подвійні лапки"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Одинарні лапки"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Крапка"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Квадратний корінь"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Пі"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Дельта"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Торговельна марка"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Через"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Зірочка"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Решітка"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Три крапки"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Нижні подвійні лапки"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift увімкнено"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Caps Lock увімкнено"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift вимкнено"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Режим символів"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Режим букв і цифр"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Режим набору номера"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Режим набору символів"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Голос. ввід"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Голос. ввід наразі не підтрим. для вашої мови, але можна користуватися англійською."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Голосовий ввід використовує розпізнавання мовлення Google. Застосовується "<a href="http://m.google.com/privacy">"Політика конфіденційності для мобільних пристроїв"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Увімк. відгуки корист."</string> <string name="prefs_description_log" msgid="5827825607258246003">"Допоможіть покращ. редактор методу введ., автомат. надсилаючи в Google статистику використ. та звіти про збої."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавіатури"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Німецька клавіатура QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Англійська (Великобританія)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Англійська (США)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Режим вивчення зручності у використанні"</string> diff --git a/java/res/values-vi/donottranslate-more-keys.xml b/java/res/values-vi/donottranslate-more-keys.xml new file mode 100644 index 000000000..6ef1c6bc5 --- /dev/null +++ b/java/res/values-vi/donottranslate-more-keys.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE + U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE + U+1EA3: "ả" LATIN SMALL LETTER A WITH HOOK ABOVE + U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE + U+1EA1: "ạ" LATIN SMALL LETTER A WITH DOT BELOW + U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + U+1EB1: "ằ" LATIN SMALL LETTER A WITH BREVE AND GRAVE + U+1EAF: "ắ" LATIN SMALL LETTER A WITH BREVE AND ACUTE + U+1EB3: "ẳ" LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE + U+1EB5: "ẵ" LATIN SMALL LETTER A WITH BREVE AND TILDE + U+1EB7: "ặ" LATIN SMALL LETTER A WITH BREVE AND DOT BELOW + U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX + U+1EA7: "ầ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE + U+1EA5: "ấ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE + U+1EA9: "ẩ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + U+1EAB: "ẫ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE + U+1EAD: "ậ" LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW --> + <string name="more_keys_for_a">à,á,ả,ã,ạ,ă,ằ,ắ,ẳ,ẵ,ặ,â,ầ,ấ,ẩ,ẫ,ậ</string> + <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE + U+1EBB: "ẻ" LATIN SMALL LETTER E WITH HOOK ABOVE + U+1EBD: "ẽ" LATIN SMALL LETTER E WITH TILDE + U+1EB9: "ẹ" LATIN SMALL LETTER E WITH DOT BELOW + U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX + U+1EC1: "ề" LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE + U+1EBF: "ế" LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE + U+1EC3: "ể" LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + U+1EC5: "ễ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE + U+1EC7: "ệ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW --> + <string name="more_keys_for_e">è,é,ẻ,ẽ,ẹ,ê,ề,ế,ể,ễ,ệ</string> + <!-- U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE + U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+1EC9: "ỉ" LATIN SMALL LETTER I WITH HOOK ABOVE + U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE + U+1ECB: "ị" LATIN SMALL LETTER I WITH DOT BELOW --> + <string name="more_keys_for_i">ì,í,ỉ,ĩ,ị</string> + <!-- U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE + U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE + U+1ECF: "ỏ" LATIN SMALL LETTER O WITH HOOK ABOVE + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE + U+1ECD: "ọ" LATIN SMALL LETTER O WITH DOT BELOW + U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + U+1ED3: "ồ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE + U+1ED1: "ố" LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE + U+1ED5: "ổ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + U+1ED7: "ỗ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE + U+1ED9: "ộ" LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW + U+01A1: "ơ" LATIN SMALL LETTER O WITH HORN + U+1EDD: "ờ" LATIN SMALL LETTER O WITH HORN AND GRAVE + U+1EDB: "ớ" LATIN SMALL LETTER O WITH HORN AND ACUTE + U+1EDF: "ở" LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE + U+1EE1: "ỡ" LATIN SMALL LETTER O WITH HORN AND TILDE + U+1EE3: "ợ" LATIN SMALL LETTER O WITH HORN AND DOT BELOW --> + <string name="more_keys_for_o">ò,ó,ỏ,õ,ọ,ô,ồ,ố,ổ,ỗ,ộ,ơ,ờ,ớ,ở,ỡ,ợ</string> + <!-- U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE + U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE + U+1EE7: "ủ" LATIN SMALL LETTER U WITH HOOK ABOVE + U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE + U+1EE5: "ụ" LATIN SMALL LETTER U WITH DOT BELOW + U+01B0: "ư" LATIN SMALL LETTER U WITH HORN + U+1EEB: "ừ" LATIN SMALL LETTER U WITH HORN AND GRAVE + U+1EE9: "ứ" LATIN SMALL LETTER U WITH HORN AND ACUTE + U+1EED: "ử" LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE + U+1EEF: "ữ" LATIN SMALL LETTER U WITH HORN AND TILDE + U+1EF1: "ự" LATIN SMALL LETTER U WITH HORN AND DOT BELOW --> + <string name="more_keys_for_u">ù,ú,ủ,ũ,ụ,ư,ừ,ứ,ử,ữ,ự</string> + <!-- U+1EF3: "ỳ" LATIN SMALL LETTER Y WITH GRAVE + U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+1EF7: "ỷ" LATIN SMALL LETTER Y WITH HOOK ABOVE + U+1EF9: "ỹ" LATIN SMALL LETTER Y WITH TILDE + U+1EF5: "ỵ" LATIN SMALL LETTER Y WITH DOT BELOW --> + <string name="more_keys_for_y">ỳ,ý,ỷ,ỹ,ỵ</string> + <!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE --> + <string name="more_keys_for_d">đ</string> +</resources> diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml index e602b495a..25d1f289f 100644 --- a/java/res/values-vi/strings.xml +++ b/java/res/values-vi/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Bàn phím Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Bàn phím Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Cài đặt bàn phím Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Tùy chọn nhập"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Dịch vụ sửa chính tả của Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Trình kiểm tra chính tả Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Trình kiểm tra chính tả Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Cài đặt kiểm tra chính tả"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Sử dụng dữ liệu gần"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Dùng thuật toán gần, như của bàn phím để k.tra chính tả"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Tra cứu tên liên hệ"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Âm thanh khi nhấn phím"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Cửa sổ bật lên khi nhấn phím"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"Sửa văn bản"</string> <string name="misc_category" msgid="6894192814868233453">"Tùy chọn khác"</string> <string name="advanced_settings" msgid="362895144495591463">"Cài đặt nâng cao"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Tùy chọn cho người dùng chuyên gia"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Tùy chọn dành cho chuyên gia"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Loại bỏ hiển thị phím trễ"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Không có tgian trễ"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Mặc định"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Luôn hiển thị"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Hiển thị trên chế độ khổ đứng"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Luôn ẩn"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Hiển thị phím cài đặt"</string> <string name="auto_correction" msgid="4979925752001319458">"Tự động sửa"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Phím cách và dấu câu tự động sửa từ nhập sai"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Tắt"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Đã lưu"</string> <string name="label_go_key" msgid="1635148082137219148">"Tìm"</string> <string name="label_next_key" msgid="362972844525672568">"Tiếp theo"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Trước"</string> <string name="label_done_key" msgid="2441578748772529288">"Xong"</string> <string name="label_send_key" msgid="2815056534433717444">"Gửi"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Không có ký tự nào được nhập"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Mã phím %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Đã bật Shift"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Đã bật viết hoa"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift đang bật (bấm để tắt)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Caps lock đang bật (bấm để tắt)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Xóa"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Biểu tượng"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Chữ cái"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Nhập dữ liệu bằng giọng nói"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Mặt cười"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Quay lại"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Dấu phẩy"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Dấu chấm"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"Dấu ngoặc trái"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"Dấu ngoặc phải"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Dấu hai chấm"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Dấu chấm phẩy"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Dấu hỏi chấm"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Dấu chấm hỏi"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Dấu ngoặc kép"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Dấu nháy đơn"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Dấu chấm"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Dấu khai căn"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Số Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Thương hiệu"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Dấu phần trăm"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Dấu sao"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Dấu thăng"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Dấu ba chấm"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Dấu nháy kép dưới"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Đã bật Shift"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Đã bật Caps lock"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Đã tắt Shift"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Chế độ biểu tượng"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Chế độ chữ cái"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Chế độ điện thoại"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Chế độ biểu tượng điện thoại"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Nhập liệu bằng giọng nói"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Nhập liệu bằng giọng nói hiện không được hỗ trợ cho ngôn ngữ của bạn nhưng hoạt động với ngôn ngữ tiếng Anh."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Nhập liệu bằng giọng nói sử dụng nhận dạng giọng nói của Google. Áp dụng "<a href="http://m.google.com/privacy">"Chính sách bảo mật dành cho điện thoại di động"</a>"."</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Bật phản hồi của người dùng"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Giúp nâng cao trình chỉnh sửa phương thức nhập này bằng cách tự động gửi thống kê sử dụng và báo cáo sự cố cho Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Chủ đề bàn phím"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"Bàn phím QWERTY tiếng Đức"</string> <string name="subtype_en_GB" msgid="88170601942311355">"Tiếng Anh (Anh)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"Tiếng Anh (Mỹ)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Chế độ nghiên cứu tính khả dụng"</string> diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index c3adf23c0..ef42b7f7f 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android 键盘"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 键盘 (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android 键盘设置"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"输入选项"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android 更正"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 拼写检查工具"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼写检查工具 (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"拼写检查设置"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"使用邻近度数据"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"使用类似键盘的邻近度算法进行拼写检查"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查找联系人姓名"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼写检查工具会使用您的联系人列表中的条目"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键时振动"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"按键时播放音效"</string> <string name="popup_on_keypress" msgid="123894815723512944">"按键时显示弹出窗口"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"文本更正"</string> <string name="misc_category" msgid="6894192814868233453">"其他选项"</string> <string name="advanced_settings" msgid="362895144495591463">"高级设置"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"适合于资深用户的选项"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"高级选项"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"关闭弹出键时的延迟"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"无延迟"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"默认"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"始终显示"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"以纵向模式显示"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"始终隐藏"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"显示设置键"</string> <string name="auto_correction" msgid="4979925752001319458">"自动更正"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"按空格键和标点可自动更正错别字"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"关闭"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已保存"</string> <string name="label_go_key" msgid="1635148082137219148">"开始"</string> <string name="label_next_key" msgid="362972844525672568">"下一步"</string> + <string name="label_previous_key" msgid="1211868118071386787">"后退"</string> <string name="label_done_key" msgid="2441578748772529288">"完成"</string> <string name="label_send_key" msgid="2815056534433717444">"发送"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"未输入文字"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"键码为 %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 已启用"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Caps lock 已启用"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 模式已启用(点按即可停用)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"大写锁定已启用(点按即可停用)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"删除"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"符号"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"字母"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"语音输入"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"笑脸"</string> <string name="spoken_description_return" msgid="8178083177238315647">"返回"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"逗号"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"句号"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左括号"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右括号"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"冒号"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"分号"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"感叹号"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"问号"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"双引号"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"单引号"</string> <string name="spoken_description_dot" msgid="40711082435231673">"点"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"圆周率"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"商标符号"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"百分号"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"星号"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"井号"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略号"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"低双引号"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 模式已启用"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"大写锁定已启用"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 模式已停用"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"符号模式"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"字母模式"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"电话模式"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"电话符号模式"</string> <string name="voice_warning_title" msgid="4419354150908395008">"语音输入"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"语音输入功能当前还不支持您的语言,您只能输入英语语音。"</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"语音输入采用了 Google 的语音识别技术,因此请遵守"<a href="http://m.google.com/privacy">"“Google 移动”隐私权政策"</a>"。"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"启用用户反馈"</string> <string name="prefs_description_log" msgid="5827825607258246003">"自动向 Google 发送使用情况统计信息和崩溃报告,帮助改进该输入法编辑器。"</string> <string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"德语 QWERTY 键盘"</string> <string name="subtype_en_GB" msgid="88170601942311355">"英语(英国)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"英语(美国)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"可用性研究模式"</string> diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index 8d60fb7cd..a2c2f0250 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Android 鍵盤"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Android 鍵盤 (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Android 鍵盤設定"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"輸入選項"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Android 拼字修正服務"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Android 拼字檢查"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Android 拼字檢查 (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"拼字檢查設定"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"使用鄰近資料"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"運用類似鍵盤的鄰近演算法進行拼字檢查"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"查詢聯絡人姓名"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"拼字檢查程式使用您的聯絡人清單項目"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"按鍵時播放音效"</string> <string name="popup_on_keypress" msgid="123894815723512944">"按鍵時顯示彈出式視窗"</string> @@ -34,7 +36,13 @@ <string name="correction_category" msgid="2236750915056607613">"文字修正"</string> <string name="misc_category" msgid="6894192814868233453">"其他選項"</string> <string name="advanced_settings" msgid="362895144495591463">"進階設定"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"提供給專業使用者的選項"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"進階選項"</string> + <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) --> + <skip /> + <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) --> + <skip /> + <!-- no translation found for suppress_language_switch_key (8003788410354806368) --> + <skip /> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"關閉彈出式鍵盤的延遲時間"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"不延遲"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"預設"</string> @@ -50,7 +58,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"一律顯示"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"以垂直模式顯示"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"永遠隱藏"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"顯示設定金鑰"</string> <string name="auto_correction" msgid="4979925752001319458">"自動修正"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"按空白鍵或標點符號時,自動修正前面的錯字"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"關閉"</string> @@ -64,6 +71,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g>:已儲存"</string> <string name="label_go_key" msgid="1635148082137219148">"開始"</string> <string name="label_next_key" msgid="362972844525672568">"繼續"</string> + <string name="label_previous_key" msgid="1211868118071386787">"上一步"</string> <string name="label_done_key" msgid="2441578748772529288">"完成"</string> <string name="label_send_key" msgid="2815056534433717444">"傳送"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +84,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"未輸入文字"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"按鍵代碼 %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift 鍵"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"Shift 鍵已啟用"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"大寫鎖定已啟用"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"Shift 鍵已開啟 (輕按即可停用)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"大寫鎖定已開啟 (輕按即可停用)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"刪除"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"符號"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"字母"</string> @@ -88,26 +96,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"語音輸入"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"笑臉"</string> <string name="spoken_description_return" msgid="8178083177238315647">"返回"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"逗號"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"句號"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"左括弧"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"右括弧"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"冒號"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"分號"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"驚嘆號"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"問號"</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"雙引號"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"單引號"</string> <string name="spoken_description_dot" msgid="40711082435231673">"點"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"平方根"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"圓周率"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"商標"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"百分比"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"星號"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"井字鍵"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"省略符號"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"下雙引號"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"Shift 鍵已啟用"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"大寫鎖定已啟用"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"Shift 鍵已停用"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"符號模式"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"字母模式"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"撥號模式"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"撥號符號模式"</string> <string name="voice_warning_title" msgid="4419354150908395008">"語音輸入"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"語音輸入目前不支援您的語言,但是可以辨識英文。"</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"語音輸入使用 Google 的語音辨識功能,並遵循《"<a href="http://m.google.com/privacy">"行動服務隱私權政策"</a>"》。"</string> @@ -144,7 +140,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"啟用使用者意見回饋"</string> <string name="prefs_description_log" msgid="5827825607258246003">"自動將使用統計資料和當機報告傳送給 Google,協助改善這個輸入法編輯器。"</string> <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"德文 QWERTY"</string> <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英式)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美式)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"使用性研究模式"</string> diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml index 072d17cba..3646a85ed 100644 --- a/java/res/values-zu/strings.xml +++ b/java/res/values-zu/strings.xml @@ -21,12 +21,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="english_ime_name" msgid="7252517407088836577">"Ikhibhodi ye-Android"</string> + <string name="aosp_android_keyboard_ime_name" msgid="7877134937939182296">"Ikhibhodi ye-Android (AOSP)"</string> <string name="english_ime_settings" msgid="6661589557206947774">"Izilungiselelo zekhibhodi ye-Android"</string> <string name="english_ime_input_options" msgid="3909945612939668554">"Okukhethwa kukho kokungenayo"</string> - <string name="spell_checker_service_name" msgid="2003013122022285508">"Ukulungisa kwe-Android"</string> + <string name="spell_checker_service_name" msgid="7338064335159755926">"Isihloli sokupela se-Android"</string> + <string name="aosp_spell_checker_service_name" msgid="6985142605330377819">"Isihloli sokupela se-Android (AOSP)"</string> <string name="android_spell_checker_settings" msgid="5822324635435443689">"Izilungiselelo zokuhlola ukupela"</string> - <string name="use_proximity_option_title" msgid="7469233942295924620">"Sebenzisa imininingo ye-proximity"</string> - <string name="use_proximity_option_summary" msgid="2857708859847261945">"Sebenzisa i-proximity algorithm efana ne-keyboard ukuhlola ukupela"</string> + <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Bheka amagama woxhumana nabo"</string> + <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Isihloli sokupela sisebenzisa okungenayo kusuka kuhlu lalabo oxhumana nabo"</string> <string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string> <string name="sound_on_keypress" msgid="6093592297198243644">"Umsindo wokucindezela ukhiye"</string> <string name="popup_on_keypress" msgid="123894815723512944">"Ugaxekile ngokucindezela ukhiye"</string> @@ -34,7 +36,10 @@ <string name="correction_category" msgid="2236750915056607613">"Ukulungiswa kombhalo"</string> <string name="misc_category" msgid="6894192814868233453">"Okunye okukhethwa kukho"</string> <string name="advanced_settings" msgid="362895144495591463">"Izilungiselelo ezithuthukisiwe"</string> - <string name="advanced_settings_summary" msgid="5193513161106637254">"Okukhethwa kukho kompetha babasebenzi"</string> + <string name="advanced_settings_summary" msgid="4487980456152830271">"Izinketho zezingcwenti"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Shintshela kwezinye izindlela zokungena"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ukhiye wokushintsha ilimi ubandakanya ezinye izindlela zokungenayo"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ukhiye wokushintshela wokuvimbela ulimi"</string> <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ukuvela kokhiye cashisa ukulibazisa"</string> <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Cha ukulibazisa"</string> <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string> @@ -50,7 +55,6 @@ <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Bonisa njalo"</string> <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3551821800439659812">"Bonisa kwimodi emile"</string> <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Fihla njalo"</string> - <string name="prefs_settings_key" msgid="4623341240804046498">"Bonisa ukhiye wezilungiselelo"</string> <string name="auto_correction" msgid="4979925752001319458">"Ukulungisa okuzenzakalelayo"</string> <string name="auto_correction_summary" msgid="5625751551134658006">"Ibha yesikhala nokubhala ngamagama amakhulu kulungisa amaphutha amagama athayiphwe kabi"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Valiwe"</string> @@ -64,6 +68,7 @@ <string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : Kulondoloziwe"</string> <string name="label_go_key" msgid="1635148082137219148">"Iya"</string> <string name="label_next_key" msgid="362972844525672568">"Okulandelayo"</string> + <string name="label_previous_key" msgid="1211868118071386787">"Eledlule"</string> <string name="label_done_key" msgid="2441578748772529288">"Kwenziwe"</string> <string name="label_send_key" msgid="2815056534433717444">"Thumela"</string> <string name="label_to_alpha_key" msgid="4793983863798817523">"ABC"</string> @@ -76,8 +81,8 @@ <string name="spoken_no_text_entered" msgid="7479685225597344496">"Awukho umbhalo ofakiwe"</string> <string name="spoken_description_unknown" msgid="3197434010402179157">"Ikhodi yokhiye %d"</string> <string name="spoken_description_shift" msgid="244197883292549308">"Shift"</string> - <string name="spoken_description_shift_shifted" msgid="954941524766465022">"I-Shift inikwe amandla"</string> - <string name="spoken_description_caps_lock" msgid="5660626444912131764">"Ukunika amandla ukhiye wombhalo ngamagama amakhulu"</string> + <string name="spoken_description_shift_shifted" msgid="1681877323344195035">"U-Shift uvuliwe (thepha ukuwuvimbela)"</string> + <string name="spoken_description_caps_lock" msgid="3276478269526304432">"Ofeleba bavuliwe (thepha ukubavimbela)"</string> <string name="spoken_description_delete" msgid="8740376944276199801">"Susa"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Amasimbuli"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Imbhalo"</string> @@ -88,26 +93,14 @@ <string name="spoken_description_mic" msgid="615536748882611950">"Okungenayo kwezwi"</string> <string name="spoken_description_smiley" msgid="2256309826200113918">"Ubuso-obumomothekayo"</string> <string name="spoken_description_return" msgid="8178083177238315647">"Buyisela"</string> - <string name="spoken_description_comma" msgid="4970844442999724586">"Ikhefu"</string> - <string name="spoken_description_period" msgid="5286614628077903945">"Isikhathi"</string> - <string name="spoken_description_left_parenthesis" msgid="8524822120595052415">"ama-parenthesis esobunxele"</string> - <string name="spoken_description_right_parenthesis" msgid="1085757995851933164">"I-parenthesis yesokudla"</string> - <string name="spoken_description_colon" msgid="4312420908484277077">"Ikholoni"</string> - <string name="spoken_description_semicolon" msgid="37737920987155179">"Ikhefanangqi"</string> - <string name="spoken_description_exclamation_mark" msgid="2625684427460737157">"Uphawu lokumemeza"</string> - <string name="spoken_description_question_mark" msgid="7074097784255379666">"Imaki yombuzo."</string> - <string name="spoken_description_double_quote" msgid="5485320575389905967">"Ukusho kabili"</string> - <string name="spoken_description_single_quote" msgid="4451320362665463938">"Isibizo esisodwa"</string> <string name="spoken_description_dot" msgid="40711082435231673">"Icashazi"</string> - <string name="spoken_description_square_root" msgid="190595160284757811">"Impande yesikwele"</string> - <string name="spoken_description_pi" msgid="4554418247799952239">"Pi"</string> - <string name="spoken_description_delta" msgid="3607948313655721579">"i-Delta"</string> - <string name="spoken_description_trademark" msgid="475877774077871369">"Uphawu lomkhiqizo"</string> - <string name="spoken_description_care_of" msgid="7492800237237796530">"Ukunakekela ko"</string> - <string name="spoken_description_star" msgid="1009742725387231977">"Inkanyezi"</string> - <string name="spoken_description_pound" msgid="5530577649206922631">"Iphawundi"</string> - <string name="spoken_description_ellipsis" msgid="1687670869947652062">"Ellipsis"</string> - <string name="spoken_description_low_double_quote" msgid="3551394572784840975">"Isilinganiso esikabili esiphansi"</string> + <string name="spoken_description_shiftmode_on" msgid="5700440798609574589">"U-Shift uvunyelwe"</string> + <string name="spoken_description_shiftmode_locked" msgid="593175803181701830">"Ofeleba bavunyelwe"</string> + <string name="spoken_description_shiftmode_off" msgid="657219998449174808">"U-Shift uvimbelwe"</string> + <string name="spoken_description_mode_symbol" msgid="7183343879909747642">"Imodi yezimpawu"</string> + <string name="spoken_description_mode_alpha" msgid="3528307674390156956">"Imodi yezinhlamvu"</string> + <string name="spoken_description_mode_phone" msgid="6520207943132026264">"Imodi yefoni"</string> + <string name="spoken_description_mode_phone_shift" msgid="5499629753962641227">"Imodi yezimpawu zefoni"</string> <string name="voice_warning_title" msgid="4419354150908395008">"Okufakwa ngezwi"</string> <string name="voice_warning_locale_not_supported" msgid="637923019716442333">"Okufakwa ngezwi akusekelwa olimini lwakho, kodwa kuyasebenza nge-English."</string> <string name="voice_warning_may_not_understand" msgid="5596289095878251072">"Okufakwayo ngezwi kusebenzisa ukufanisa izwi kwe-Google. "<a href="http://m.google.com/privacy">"Inqubomgomo Yobumfihlo Yefoni"</a>" iyasebenza."</string> @@ -144,7 +137,6 @@ <string name="prefs_enable_log" msgid="6620424505072963557">"Vumela impendulo yomsebenzisi"</string> <string name="prefs_description_log" msgid="5827825607258246003">"Siza ukuthuthukisa lo mhleli wendlela yokufakwa ngokusithumela ngokuzenzakalela izibalo zokusetshenziswa nokukhubeka ku-Google."</string> <string name="keyboard_layout" msgid="8451164783510487501">"Indikimba yekhibhodi"</string> - <string name="subtype_de_qwerty" msgid="3358900499589259491">"i-QWERTY yesi-German"</string> <string name="subtype_en_GB" msgid="88170601942311355">"i-English(UK)"</string> <string name="subtype_en_US" msgid="6160452336634534239">"i-English (US)"</string> <string name="prefs_usability_study_mode" msgid="1261130555134595254">"Imodi yesitadi yokusebenziseka"</string> diff --git a/java/res/values-de-rZZ/donottranslate-more-keys.xml b/java/res/values/additional-proximitychars.xml index e7ec5e152..03d10d5d8 100644 --- a/java/res/values-de-rZZ/donottranslate-more-keys.xml +++ b/java/res/values/additional-proximitychars.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -18,6 +18,6 @@ */ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="more_keys_for_y">6</string> - <string name="more_keys_for_z"></string> + <string-array name="additional_proximitychars"> + </string-array> </resources> diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index 0c9ca4f4a..e619ad0a8 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -18,15 +18,18 @@ <declare-styleable name="KeyboardTheme"> <!-- Keyboard style --> <attr name="keyboardStyle" format="reference" /> + <!-- TODO: Get rid of latinKeyboardStyle --> <!-- LatinKeyboard style --> <attr name="latinKeyboardStyle" format="reference" /> <!-- KeyboardView style --> <attr name="keyboardViewStyle" format="reference" /> - <!-- MiniKeyboard style --> - <attr name="miniKeyboardStyle" format="reference" /> - <!-- MiniKeyboardView style --> - <attr name="miniKeyboardViewStyle" format="reference" /> - <attr name="miniKeyboardPanelStyle" format="reference" /> + <!-- LatinKeyboardView style --> + <attr name="latinKeyboardViewStyle" format="reference" /> + <!-- MoreKeysKeyboard style --> + <attr name="moreKeysKeyboardStyle" format="reference" /> + <!-- MoreKeysKeyboardView style --> + <attr name="moreKeysKeyboardViewStyle" format="reference" /> + <attr name="moreKeysKeyboardPanelStyle" format="reference" /> <!-- Suggestions strip style --> <attr name="suggestionsStripBackgroundStyle" format="reference" /> <attr name="suggestionsViewStyle" format="reference" /> @@ -57,16 +60,16 @@ <attr name="keyHintLetterRatio" format="float" /> <!-- Size of the text for hint label, in the proportion of key height. --> <attr name="keyHintLabelRatio" format="float" /> - <!-- Size of the text for upper case letter, in the proportion of key height. --> - <attr name="keyUppercaseLetterRatio" format="float" /> + <!-- Size of the text for shifted letter hint, in the proportion of key height. --> + <attr name="keyShiftedLetterHintRatio" format="float" /> <!-- Horizontal padding of left/right aligned key label to the edge of the key. --> <attr name="keyLabelHorizontalPadding" format="dimension" /> <!-- Top and right padding of hint letter to the edge of the key.--> <attr name="keyHintLetterPadding" format="dimension" /> <!-- Bottom padding of popup hint letter "..." to the edge of the key.--> <attr name="keyPopupHintLetterPadding" format="dimension" /> - <!-- Top and right padding of upper case letter to the edge of the key.--> - <attr name="keyUppercaseLetterPadding" format="dimension" /> + <!-- Top and right padding of shifted letter hint to the edge of the key.--> + <attr name="keyShiftedLetterHintPadding" format="dimension" /> <!-- Color to use for the label in a key. --> <attr name="keyTextColor" format="color" /> @@ -76,9 +79,9 @@ <attr name="keyHintLetterColor" format="color" /> <!-- Key hint label color --> <attr name="keyHintLabelColor" format="color" /> - <!-- Upper case letter colors --> - <attr name="keyUppercaseLetterInactivatedColor" format="color" /> - <attr name="keyUppercaseLetterActivatedColor" format="color" /> + <!-- Shifted letter hint colors --> + <attr name="keyShiftedLetterHintInactivatedColor" format="color" /> + <attr name="keyShiftedLetterHintActivatedColor" format="color" /> <!-- Layout resource for key press feedback.--> <attr name="keyPreviewLayout" format="reference" /> @@ -100,6 +103,8 @@ <attr name="keyPreviewHeight" format="dimension" /> <!-- Size of the text for key press feedback popup, int the proportion of key height --> <attr name="keyPreviewTextRatio" format="float" /> + <!-- Delay after key releasing and key press feedback dismissing in millisecond --> + <attr name="keyPreviewLingerTimeout" format="integer" /> <!-- Amount to offset the touch Y coordinate by, for bias correction. --> <attr name="verticalCorrection" format="dimension" /> @@ -109,7 +114,7 @@ <attr name="shadowColor" format="color" /> <attr name="shadowRadius" format="float" /> - <attr name="backgroundDimAmount" format="float" /> + <attr name="backgroundDimAlpha" format="integer" /> <attr name="keyTextStyle" format="enum"> <!-- This should be aligned with Typeface.NORMAL etc. --> @@ -120,6 +125,42 @@ </attr> </declare-styleable> + <declare-styleable name="LatinKeyboardView"> + <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" /> + <attr name="autoCorrectionSpacebarLedIcon" format="reference" /> + <!-- Size of the text for spacebar language label, in the proportion of key height. --> + <attr name="spacebarTextRatio" format="fraction" /> + <attr name="spacebarTextColor" format="color" /> + <attr name="spacebarTextShadowColor" format="color" /> + <!-- Fadeout animator for spacebar language label. --> + <attr name="languageOnSpacebarFadeoutAnimator" format="reference" /> + <!-- Fadeout and fadein animator for altCodeWhileTyping keys. --> + <attr name="altCodeKeyWhileTypingFadeoutAnimator" format="reference" /> + <attr name="altCodeKeyWhileTypingFadeinAnimator" format="reference" /> + <!-- Key detection hysteresis distance. --> + <attr name="keyHysteresisDistance" format="dimension" /> + <!-- Touch noise threshold time in millisecond --> + <attr name="touchNoiseThresholdTime" format="integer" /> + <!-- Touch noise threshold distance in millimeter --> + <attr name="touchNoiseThresholdDistance" format="dimension" /> + <!-- Sliding key input enable --> + <attr name="slidingKeyInputEnable" format="boolean" /> + <!-- Key repeat start timeout --> + <attr name="keyRepeatStartTimeout" format="integer" /> + <!-- Key repeat interval in millisecond. --> + <attr name="keyRepeatInterval" format="integer" /> + <!-- Long press timeout of letter key in millisecond. --> + <attr name="longPressKeyTimeout" format="integer" /> + <!-- Long press timeout of shift key in millisecond. --> + <attr name="longPressShiftKeyTimeout" format="integer" /> + <!-- Long press timeout of space key in millisecond. --> + <attr name="longPressSpaceKeyTimeout" format="integer" /> + <!-- Ignore special key timeout while typing in millisecond. --> + <attr name="ignoreAltCodeKeyTimeout" format="integer" /> + <!-- More keys keyboard will shown at touched point. --> + <attr name="showMoreKeysKeyboardAtTouchedPoint" format="boolean" /> + </declare-styleable> + <declare-styleable name="SuggestionsView"> <attr name="suggestionStripOption" format="integer"> <!-- This should be aligned with SuggestionsViewParams.AUTO_CORRECT_* and etc. --> @@ -127,9 +168,11 @@ <flag name="autoCorrectUnderline" value="0x02" /> <flag name="validTypedWordBold" value="0x04" /> </attr> + <attr name="colorValidTypedWord" format="color" /> <attr name="colorTypedWord" format="color" /> <attr name="colorAutoCorrect" format="color" /> <attr name="colorSuggested" format="color" /> + <attr name="alphaValidTypedWord" format="integer" /> <attr name="alphaTypedWord" format="integer" /> <attr name="alphaAutoCorrect" format="integer" /> <attr name="alphaSuggested" format="integer" /> @@ -164,10 +207,6 @@ <attr name="verticalGap" format="dimension|fraction" /> <!-- More keys keyboard layout template --> <attr name="moreKeysTemplate" format="reference" /> - <!-- Locale of the keyboard layout --> - <attr name="keyboardLocale" format="string" /> - <!-- True if the keyboard is Right-To-Left --> - <attr name="isRtlKeyboard" format="boolean" /> <!-- Icon set for key top and key preview. --> <attr name="iconShiftKey" format="reference" /> <attr name="iconDeleteKey" format="reference" /> @@ -178,15 +217,26 @@ <attr name="iconTabKey" format="reference" /> <attr name="iconShortcutKey" format="reference" /> <attr name="iconShortcutForLabel" format="reference" /> - <attr name="iconShiftedShiftKey" format="reference" /> + <attr name="iconSpaceKeyForNumberLayout" format="reference" /> + <attr name="iconShiftKeyShifted" format="reference" /> + <attr name="iconDisabledShortcutKey" format="reference" /> <attr name="iconPreviewTabKey" format="reference" /> + <attr name="iconLanguageSwitchKey" format="reference" /> </declare-styleable> <declare-styleable name="Keyboard_Key"> <!-- The unicode value that this key outputs. --> <attr name="code" format="integer" /> + <!-- The alternate unicode value that this key outputs while typing. --> + <attr name="altCode" format="integer" /> <!-- The keys to display in the more keys keyboard. --> <attr name="moreKeys" format="string" /> + <!-- The keys to display in the more keys keyboard in addition to moreKeys. + The additional more keys are inserted at the '%' markers in the moreKeys if any. + They are inserted at the head of moreKeys if none. + If there are remaining entries of additionalMoreKeys even after all '%' markers have + been replaced, those remaining entries are appended at the end of moreKeys. --> + <attr name="additionalMoreKeys" format="string" /> <!-- Maximum column of more keys keyboard --> <attr name="maxMoreKeysColumn" format="integer" /> <attr name="backgroundType" format="enum"> @@ -194,19 +244,26 @@ <enum name="normal" value="0" /> <enum name="functional" value="1" /> <enum name="action" value="2" /> - <enum name="sticky" value="3" /> + <enum name="stickyOff" value="3" /> + <enum name="stickyOn" value="4" /> + </attr> + <!-- The key action flags. --> + <attr name="keyActionFlags" format="integer"> + <!-- This should be aligned with Key.ACTION_FLAGS_* --> + <flag name="isRepeatable" value="0x01" /> + <flag name="noKeyPreview" value="0x02" /> + <flag name="altCodeWhileTyping" value="0x04" /> + <flag name="enableLongPress" value="0x08" /> </attr> - <!-- Whether long-pressing on this key will make it repeat. --> - <attr name="isRepeatable" format="boolean" /> <!-- The string of characters to output when this key is pressed. --> <attr name="keyOutputText" format="string" /> <!-- The label to display on the key. --> <attr name="keyLabel" format="string" /> <!-- The hint label to display on the key in conjunction with the label. --> <attr name="keyHintLabel" format="string" /> - <!-- The key label option. --> - <attr name="keyLabelOption" format="integer"> - <!-- This should be aligned with Key.LABEL_OPTION_* --> + <!-- The key label flags. --> + <attr name="keyLabelFlags" format="integer"> + <!-- This should be aligned with Key.LABEL_FLAGS__* --> <flag name="alignLeft" value="0x01" /> <flag name="alignRight" value="0x02" /> <flag name="alignLeftOfCenter" value="0x08" /> @@ -216,15 +273,28 @@ <flag name="followKeyLetterRatio" value="0x80" /> <flag name="followKeyHintLabelRatio" value="0x100" /> <flag name="hasPopupHint" value="0x200" /> - <flag name="hasUppercaseLetter" value="0x400" /> + <flag name="hasShiftedLetterHint" value="0x400" /> <flag name="hasHintLabel" value="0x800" /> <flag name="withIconLeft" value="0x1000" /> <flag name="withIconRight" value="0x2000" /> <flag name="autoXScale" value="0x4000" /> + <!-- If true, character case of code, altCode, moreKeys, keyOutputText, keyLabel, + or keyHintLabel will never be subject to change. --> + <flag name="preserveCase" value="0x8000" /> + <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and + keyTextInactivatedColor for the primary key top label. --> + <flag name="shiftedLetterActivated" value="0x10000" /> + <!-- If true, use EditorInfo.actionLabel for the key label. --> + <flag name="fromCustomActionLabel" value="0x20000" /> + <!-- If true, disable keyHintLabel. --> + <flag name="disableKeyHintLabel" value="0x40000000" /> + <!-- If true, disable additionalMoreKeys. --> + <flag name="disableAdditionalMoreKeys" value="0x80000000" /> </attr> <!-- The icon to display on the key instead of the label. --> <attr name="keyIcon" format="enum"> - <!-- This should be aligned with KeyboardIcons.ICON_* --> + <!-- This should be aligned with the KeyboardIconsSet.ICON_* --> + <enum name="iconUndefined" value="0" /> <enum name="iconShiftKey" value="1" /> <enum name="iconDeleteKey" value="2" /> <enum name="iconSettingsKey" value="3" /> @@ -234,21 +304,22 @@ <enum name="iconTabKey" value="7" /> <enum name="iconShortcutKey" value="8" /> <enum name="iconShortcutForLabel" value="9" /> + <enum name="iconSpaceKeyForNumberLayout" value="10" /> + <enum name="iconShiftKeyShifted" value="11" /> + <enum name="iconLanguageSwitchKey" value="14" /> </attr> - <!-- Shift key icon for shifted state --> - <attr name="keyIconShifted" format="enum"> - <!-- This should be aligned with KeyboardIcons.ICON_SHIFTED_* --> - <enum name="iconShiftedShiftKey" value="10" /> + <!-- The icon for disabled key --> + <attr name="keyIconDisabled" format="enum"> + <!-- This should be aligned with the KeyboardIconsSet.ICON_* --> + <enum name="iconDisabledShortcutKey" value="12" /> </attr> <!-- The icon to show in the popup preview. --> <attr name="keyIconPreview" format="enum"> - <!-- This should be aligned with KeyboardIcons.ICON_PREVIEW_* --> - <enum name="iconPreviewTabKey" value="11" /> + <!-- This should be aligned with the KeyboardIconsSet.ICON_* --> + <enum name="iconPreviewTabKey" value="13" /> </attr> <!-- The key style to specify a set of key attributes defined by <key_style/> --> <attr name="keyStyle" format="string" /> - <!-- The key is enabled and responds on press. --> - <attr name="enabled" format="boolean" /> <!-- Visual insets --> <attr name="visualInsetsLeft" format="dimension|fraction" /> <attr name="visualInsetsRight" format="dimension|fraction" /> @@ -273,6 +344,19 @@ </declare-styleable> <declare-styleable name="Keyboard_Case"> + <!-- This should be aligned with KeyboardSet_Element's elementName. --> + <attr name="keyboardSetElement" format="enum|string"> + <enum name="alphabet" value="0" /> + <enum name="alphabetManualShifted" value="1" /> + <enum name="alphabetAutomaticShifted" value="2" /> + <enum name="alphabetShiftLocked" value="3" /> + <enum name="alphabetShiftLockShifted" value="4" /> + <enum name="symbols" value="5" /> + <enum name="symbolsShifted" value="6" /> + <enum name="phone" value="7" /> + <enum name="phoneSymbols" value="8" /> + <enum name="number" value="9" /> + </attr> <!-- This should be aligned with KeyboardId.MODE_* --> <attr name="mode" format="enum|string"> <enum name="text" value="0" /> @@ -282,19 +366,14 @@ <enum name="phone" value="4" /> <enum name="number" value="5" /> </attr> - <attr name="navigateAction" format="boolean" /> + <attr name="navigateNext" format="boolean" /> + <attr name="navigatePrevious" format="boolean" /> <attr name="passwordInput" format="boolean" /> - <attr name="hasSettingsKey" format="boolean" /> - <!-- This should be aligned with KeyboardID.F2KEY_MODE_* --> - <attr name="f2KeyMode" format="enum"> - <enum name="none" value="0" /> - <enum name="settings" value="1" /> - <enum name="shortcutIme" value="2" /> - <enum name="shortcutImeOrSettings" value="3" /> - </attr> <attr name="clobberSettingsKey" format="boolean" /> <attr name="shortcutKeyEnabled" format="boolean" /> <attr name="hasShortcutKey" format="boolean" /> + <attr name="languageSwitchKeyEnabled" format="boolean" /> + <attr name="isMultiLine" format="boolean" /> <attr name="imeAction" format="enum"> <!-- This should be aligned with EditorInfo.IME_ACTION_* --> <enum name="actionUnspecified" value="0" /> @@ -305,6 +384,8 @@ <enum name="actionNext" value="5" /> <enum name="actionDone" value="6" /> <enum name="actionPrevious" value="7" /> + <!-- This should be aligned with KeyboardId.IME_ACTION_* --> + <enum name="actionCustomLabel" value="0x100" /> </attr> <attr name="localeCode" format="string" /> <attr name="languageCode" format="string" /> @@ -316,11 +397,26 @@ <attr name="parentStyle" format="string" /> </declare-styleable> - <declare-styleable name="LatinKeyboard"> - <attr name="autoCorrectionSpacebarLedEnabled" format="boolean" /> - <attr name="autoCorrectionSpacebarLedIcon" format="reference" /> - <attr name="disabledShortcutIcon" format="reference" /> - <attr name="spacebarTextColor" format="color" /> - <attr name="spacebarTextShadowColor" format="color" /> + <!-- TODO: Should be removed. This is no longer required if InputMethodSubtype is supported. --> + <declare-styleable name="KeyboardSet"> + <!-- Locale of the keyboard layouts --> + <attr name="keyboardLocale" format="string" /> + </declare-styleable> + + <declare-styleable name="KeyboardSet_Element"> + <!-- This should be aligned with KeyboardId.ELEMENT_* --> + <attr name="elementName" format="enum"> + <enum name="alphabet" value="0" /> + <enum name="alphabetManualShifted" value="1" /> + <enum name="alphabetAutomaticShifted" value="2" /> + <enum name="alphabetShiftLocked" value="3" /> + <enum name="alphabetShiftLockShifted" value="4" /> + <enum name="symbols" value="5" /> + <enum name="symbolsShifted" value="6" /> + <enum name="phone" value="7" /> + <enum name="phoneSymbols" value="8" /> + <enum name="number" value="9" /> + </attr> + <attr name="elementKeyboard" format="reference"/> </declare-styleable> </resources> diff --git a/java/res/values/config.xml b/java/res/values/config.xml index 3f676ab25..c51800fb0 100644 --- a/java/res/values/config.xml +++ b/java/res/values/config.xml @@ -20,14 +20,11 @@ <resources> <bool name="config_use_fullscreen_mode">false</bool> - <bool name="config_enable_show_settings_key_option">true</bool> - <bool name="config_default_show_settings_key">false</bool> <bool name="config_enable_show_voice_key_option">true</bool> <bool name="config_enable_show_popup_on_keypress_option">true</bool> <bool name="config_enable_bigram_suggestions_option">true</bool> - <bool name="config_enable_usability_study_mode_option">false</bool> - <bool name="config_sliding_key_input_enabled">true</bool> - <bool name="config_digit_more_keys_enabled">true</bool> + <!-- TODO: Disable the following configuration for production. --> + <bool name="config_enable_usability_study_mode_option">true</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">true</bool> <!-- Default value for bigram suggestion: while showing suggestions for a word should we weigh @@ -38,37 +35,43 @@ <bool name="config_default_bigram_prediction">false</bool> <bool name="config_default_sound_enabled">false</bool> <bool name="config_default_vibration_enabled">true</bool> - <bool name="config_auto_correction_spacebar_led_enabled">false</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">false</bool> - <!-- The language is never displayed if == 0, always displayed if < 0 --> - <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer> <integer name="config_delay_update_suggestions">100</integer> <integer name="config_delay_update_old_suggestions">300</integer> <integer name="config_delay_update_shift_state">100</integer> - <integer name="config_duration_of_fadeout_language_on_spacebar">50</integer> - <integer name="config_final_fadeout_percentage_of_language_on_spacebar">50</integer> - <integer name="config_delay_before_preview">0</integer> - <integer name="config_delay_after_preview">70</integer> - <integer name="config_mini_keyboard_fadein_anim_time">0</integer> - <integer name="config_mini_keyboard_fadeout_anim_time">100</integer> - <integer name="config_delay_before_key_repeat_start">400</integer> - <integer name="config_key_repeat_interval">50</integer> + <integer name="config_more_keys_keyboard_fadein_anim_time">0</integer> + <integer name="config_more_keys_keyboard_fadeout_anim_time">100</integer> <integer name="config_keyboard_grid_width">32</integer> <integer name="config_keyboard_grid_height">16</integer> + <integer name="config_double_spaces_turn_into_period_timeout">1100</integer> + <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> + <string name="config_default_keyboard_theme_index" translatable="false">5</string> + <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for KeyboardView + --> + <integer name="config_key_preview_linger_timeout">70</integer> + <!-- + Configuration for LatinKeyboardView + --> + <dimen name="config_key_hysteresis_distance">0.05in</dimen> + <integer name="config_touch_noise_threshold_time">40</integer> + <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen> + <bool name="config_sliding_key_input_enabled">true</bool> + <integer name="config_key_repeat_start_timeout">400</integer> + <integer name="config_key_repeat_interval">50</integer> <integer name="config_long_press_key_timeout">400</integer> <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 --> <integer name="config_long_press_shift_key_timeout">1200</integer> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> - <integer name="config_long_press_space_key_timeout">@integer/config_long_press_key_timeout</integer> - <integer name="config_touch_noise_threshold_millis">40</integer> - <integer name="config_double_spaces_turn_into_period_timeout">1100</integer> - <integer name="config_ignore_special_key_timeout">700</integer> - <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen> - <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> - <string name="config_default_keyboard_theme_id" translatable="false">5</string> - <string name="config_text_size_of_language_on_spacebar" translatable="false">small</string> - <integer name="config_max_more_keys_column">5</integer> + <integer name="config_long_press_space_key_timeout"> + @integer/config_long_press_key_timeout</integer> + <integer name="config_ignore_alt_code_key_timeout">700</integer> + <!-- Showing more keys keyboard, just above the touched point if true, aligned to the key if + false --> + <bool name="config_show_more_keys_keyboard_at_touched_point">false</bool> + <!-- + Configuration for auto correction + --> <string-array name="auto_correction_threshold_values" translatable="false"> <!-- Off, When auto correction setting is Off, this value is not used. --> <item></item> @@ -81,9 +84,11 @@ will be subject to auto-correction. --> <item>0</item> </string-array> - <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare a word to be "likely" --> - <string name="spellchecker_likely_threshold_value" translatable="false">0.11</string> - <!-- Threshold of the normalized score of any dictionary lookup to be offered as a suggestion by the spell checker --> + <!-- Threshold of the normalized score of the best suggestion for the spell checker to declare + a word to be "recommended" --> + <string name="spellchecker_recommended_threshold_value" translatable="false">0.11</string> + <!-- Threshold of the normalized score of any dictionary lookup to be offered as a suggestion + by the spell checker --> <string name="spellchecker_suggestion_threshold_value" translatable="false">0.03</string> <!-- Screen metrics for logging. 0 = "mdpi phone screen" diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml index 352141ca6..37720ce72 100644 --- a/java/res/values/dimens.xml +++ b/java/res/values/dimens.xml @@ -26,8 +26,8 @@ <dimen name="popup_key_height">0.330in</dimen> - <dimen name="mini_keyboard_horizontal_edges_padding">16dip</dimen> - <dimen name="mini_keyboard_key_horizontal_padding">8dip</dimen> + <dimen name="more_keys_keyboard_horizontal_edges_padding">16dip</dimen> + <dimen name="more_keys_keyboard_key_horizontal_padding">8dip</dimen> <fraction name="keyboard_top_padding">1.556%p</fraction> <fraction name="keyboard_bottom_padding">4.669%p</fraction> @@ -48,13 +48,13 @@ <fraction name="keyboard_bottom_padding_ics">4.669%p</fraction> <fraction name="key_bottom_gap_ics">6.127%p</fraction> <fraction name="key_horizontal_gap_ics">1.739%p</fraction> - <dimen name="mini_keyboard_horizontal_edges_padding_ics">4dip</dimen> + <dimen name="more_keys_keyboard_horizontal_edges_padding_ics">4dip</dimen> <!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. --> <!-- popup_key_height x 1.2 --> - <dimen name="mini_keyboard_slide_allowance">0.396in</dimen> + <dimen name="more_keys_keyboard_slide_allowance">0.396in</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-0.330in</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-0.330in</dimen> <!-- We use "inch", not "dip" because this value tries dealing with physical distance related to user's finger. --> <dimen name="keyboard_vertical_correction">0.0in</dimen> @@ -66,6 +66,7 @@ <fraction name="key_hint_label_ratio">44%</fraction> <fraction name="key_uppercase_letter_ratio">35%</fraction> <fraction name="key_preview_text_ratio">82%</fraction> + <fraction name="spacebar_text_ratio">33.735%</fraction> <dimen name="key_preview_height">80sp</dimen> <dimen name="key_preview_offset">0.1in</dimen> @@ -76,6 +77,8 @@ <dimen name="key_preview_height_ics">80sp</dimen> <dimen name="key_preview_offset_ics">0.05in</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-0.165in</dimen> <dimen name="suggestions_strip_height">40dip</dimen> <dimen name="more_suggestions_key_horizontal_padding">12dip</dimen> @@ -86,8 +89,6 @@ <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> <fraction name="more_suggestions_info_ratio">18%</fraction> - <!-- key_preview_backing_height = more_suggestions_row_height * max_more_suggestions_row --> - <dimen name="key_preview_backing_height">240dip</dimen> <dimen name="suggestions_strip_padding">0dip</dimen> <dimen name="suggestion_min_width">44dip</dimen> <dimen name="suggestion_padding">6dip</dimen> @@ -95,6 +96,4 @@ <dimen name="more_suggestions_hint_text_size">27dip</dimen> <integer name="suggestions_count_in_strip">3</integer> <integer name="center_suggestion_percentile">36</integer> - - <dimen name="key_hysteresis_distance">0.05in</dimen> </resources> diff --git a/java/res/values/donottranslate-more-keys.xml b/java/res/values/donottranslate-more-keys.xml index 6c7753999..6577acdb9 100644 --- a/java/res/values/donottranslate-more-keys.xml +++ b/java/res/values/donottranslate-more-keys.xml @@ -19,43 +19,67 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="more_keys_for_a"></string> - <string name="more_keys_for_e">3</string> - <string name="more_keys_for_i">8</string> - <string name="more_keys_for_o">9</string> - <string name="more_keys_for_u">7</string> + <string name="more_keys_for_e"></string> + <string name="more_keys_for_i"></string> + <string name="more_keys_for_o"></string> + <string name="more_keys_for_u"></string> <string name="more_keys_for_s"></string> <string name="more_keys_for_n"></string> <string name="more_keys_for_c"></string> - <string name="more_keys_for_y">6</string> - <string name="more_keys_for_q">1</string> - <string name="more_keys_for_w">2</string> + <string name="more_keys_for_y"></string> <string name="more_keys_for_d"></string> - <string name="more_keys_for_r">4</string> - <string name="more_keys_for_t">5</string> + <string name="more_keys_for_r"></string> + <string name="more_keys_for_t"></string> <string name="more_keys_for_z"></string> <string name="more_keys_for_k"></string> <string name="more_keys_for_l"></string> <string name="more_keys_for_g"></string> - <string name="more_keys_for_p">0</string> <string name="more_keys_for_v"></string> + <string name="keylabel_for_scandinavia_row1_11"></string> <string name="keylabel_for_scandinavia_row2_10"></string> <string name="keylabel_for_scandinavia_row2_11"></string> <string name="more_keys_for_scandinavia_row2_10"></string> <string name="more_keys_for_scandinavia_row2_11"></string> - <string name="more_keys_for_cyrillic_e"></string> - <string name="more_keys_for_cyrillic_soft_sign"></string> - <string name="more_keys_for_cyrillic_ha"></string> - <string name="more_keys_for_currency_dollar">¢,£,€,¥,₱</string> - <string name="more_keys_for_currency_euro">¢,£,$,¥,₱</string> - <string name="more_keys_for_currency_pound">¢,$,€,¥,₱</string> - <string name="more_keys_for_currency_general">¢,$,€,£,¥,₱</string> - <string name="more_keys_for_smiley">":-)|:-) ,:-(|:-( ,;-)|;-) ,:-P|:-P ,=-O|=-O ,:-*|:-* ,:O|:O ,B-)|B-) ,:-$|:-$ ,:-!|:-! ,:-[|:-[ ,O:-)|O:-) ,:-\\\\\\\\|:-\\\\\\\\ ,:\'(|:\'( ,:-D|:-D "</string> - <string name="more_keys_for_punctuation">"\\,,\?,!,:,-,\',\",(,),/,;,+,&,\@"</string> - <integer name="mini_keyboard_column_for_punctuation">7</integer> + <!-- U+0449: "щ" CYRILLIC SMALL LETTER SHCHA --> + <string name="keylabel_for_cyrillic_shcha">щ</string> + <!-- U+044B: "ы" CYRILLIC SMALL LETTER YERU --> + <string name="keylabel_for_cyrillic_yery">ы</string> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I --> + <string name="keylabel_for_cyrillic_i">и</string> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <string name="keylabel_for_cyrillic_ze">з</string> + <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE --> + <string name="keylabel_for_cyrillic_tshe">ћ</string> + <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE --> + <string name="keylabel_for_cyrillic_dze">ѕ</string> + <!-- U+0452: "ђ" CYRILLIC SMALL LETTER DJE --> + <string name="keylabel_for_cyrillic_dje">ђ</string> + <string name="more_keys_for_cyrillic_u"></string> + <string name="more_keys_for_cyrillic_ye"></string> + <string name="more_keys_for_cyrillic_en"></string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_ha">ъ</string> + <string name="more_keys_for_cyrillic_yery"></string> + <string name="more_keys_for_cyrillic_o"></string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_soft_sign">ъ</string> + <string name="more_keys_for_cyrillic_ie"></string> + <string name="more_keys_for_cyrillic_i"></string> + <!-- U+00A2: "¢" CENT SIGN + U+00A3: "£" POUND SIGN + U+20AC: "€" EURO SIGN + U+00A5: "¥" YEN SIGN + U+20B1: "₱" PESO SIGN --> + <string name="more_keys_for_currency_dollar">¢,£,€,¥,₱</string> + <string name="more_keys_for_currency_euro">¢,£,$,¥,₱</string> + <string name="more_keys_for_currency_pound">¢,$,€,¥,₱</string> + <string name="more_keys_for_currency_general">¢,$,€,£,¥,₱</string> + <string name="more_keys_for_smiley">"!fixedColumnOrder!5,!hasLabels!,=-O|=-O ,:-P|:-P ,;-)|;-) ,:-(|:-( ,:-)|:-) ,:-!|:-! ,:-$|:-$ ,B-)|B-) ,:O|:O ,:-*|:-* ,:-D|:-D ,:\'(|:\'( ,:-\\\\|:-\\\\ ,O:-)|O:-) ,:-[|:-[ "</string> + <string name="more_keys_for_punctuation">"!fixedColumnOrder!8,\",\',#,-,:,!,\\,,\?,\@,&,\\%,+,;,/,(,)"</string> <string name="keyhintlabel_for_punctuation"></string> <string name="keylabel_for_popular_domain">".com"</string> <!-- popular web domains for the locale - most popular, displayed on the keyboard --> - <string name="more_keys_for_popular_domain">".net,.org,.gov,.edu"</string> + <string name="more_keys_for_popular_domain">"!hasLabels!,.net,.org,.gov,.edu"</string> <string name="keylabel_for_symbols_1">1</string> <string name="keylabel_for_symbols_2">2</string> <string name="keylabel_for_symbols_3">3</string> @@ -66,39 +90,115 @@ <string name="keylabel_for_symbols_8">8</string> <string name="keylabel_for_symbols_9">9</string> <string name="keylabel_for_symbols_0">0</string> - <string name="more_keys_for_symbols_1">¹,½,⅓,¼,⅛</string> - <string name="more_keys_for_symbols_2">²,⅔</string> - <string name="more_keys_for_symbols_3">³,¾,⅜</string> - <string name="more_keys_for_symbols_4">⁴</string> - <string name="more_keys_for_symbols_5">⅝</string> + <string name="additional_more_keys_for_symbols_1"></string> + <string name="additional_more_keys_for_symbols_2"></string> + <string name="additional_more_keys_for_symbols_3"></string> + <string name="additional_more_keys_for_symbols_4"></string> + <string name="additional_more_keys_for_symbols_5"></string> + <string name="additional_more_keys_for_symbols_6"></string> + <string name="additional_more_keys_for_symbols_7"></string> + <string name="additional_more_keys_for_symbols_8"></string> + <string name="additional_more_keys_for_symbols_9"></string> + <string name="additional_more_keys_for_symbols_0"></string> + <!-- U+00B9: "¹" SUPERSCRIPT ONE + U+00BD: "½" VULGAR FRACTION ONE HALF + U+2153: "⅓" VULGAR FRACTION ONE THIRD + U+00BC: "¼" VULGAR FRACTION ONE QUARTER + U+215B: "⅛" VULGAR FRACTION ONE EIGHTH --> + <string name="more_keys_for_symbols_1">¹,½,⅓,¼,⅛</string> + <!-- U+00B2: "²" SUPERSCRIPT TWO + U+2154: "⅔" VULGAR FRACTION TWO THIRDS --> + <string name="more_keys_for_symbols_2">²,⅔</string> + <!-- U+00B3: "³" SUPERSCRIPT THREE + U+00BE: "¾" VULGAR FRACTION THREE QUARTERS + U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS --> + <string name="more_keys_for_symbols_3">³,¾,⅜</string> + <!-- U+2074: "⁴" SUPERSCRIPT FOUR --> + <string name="more_keys_for_symbols_4">⁴</string> + <!-- U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS --> + <string name="more_keys_for_symbols_5">⅝</string> <string name="more_keys_for_symbols_6"></string> - <string name="more_keys_for_symbols_7">⅞</string> + <!-- U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS --> + <string name="more_keys_for_symbols_7">⅞</string> <string name="more_keys_for_symbols_8"></string> <string name="more_keys_for_symbols_9"></string> - <string name="more_keys_for_symbols_0">ⁿ,∅</string> + <!-- U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N + U+2205: "∅" EMPTY SET --> + <string name="more_keys_for_symbols_0">ⁿ,∅</string> + <string name="more_keys_for_am_pm">!fixedColumnOrder!2,!hasLabels!,\@string/label_time_am,\@string/label_time_pm</string> + <string name="settings_as_more_key">\@icon/settingsKey|\@integer/key_settings</string> <string name="keylabel_for_comma">,</string> - <string name="keylabel_for_f1">,</string> + <string name="more_keys_for_comma"></string> + <string name="action_next_as_more_key">!hasLabels!,\@string/label_next_key|\@integer/key_action_next</string> + <string name="action_previous_as_more_key">!hasLabels!,\@string/label_previous_key|\@integer/key_action_previous</string> <string name="keylabel_for_symbols_question">\?</string> <string name="keylabel_for_symbols_semicolon">;</string> <string name="keylabel_for_symbols_percent">%</string> - <string name="more_keys_for_comma"></string> - <string name="more_keys_for_f1"></string> - <!-- @icon/3 is iconSettingsKey --> - <string name="more_keys_for_f1_settings">\@icon/3|\@integer/key_settings</string> - <!-- @icon/7 is iconTabKey --> - <string name="more_keys_for_f1_navigate">\@icon/7|\@integer/key_tab</string> - <string name="more_keys_for_symbols_question">¿</string> + <!-- U+00BF: "¿" INVERTED QUESTION MARK --> + <string name="more_keys_for_symbols_question">¿</string> <string name="more_keys_for_symbols_semicolon"></string> - <string name="more_keys_for_symbols_percent">‰</string> + <!-- U+2030: "‰" PER MILLE SIGN --> + <string name="more_keys_for_symbols_percent">‰</string> <string name="keylabel_for_apostrophe">\'</string> <string name="keylabel_for_dash">-</string> <string name="keyhintlabel_for_apostrophe">\"</string> <string name="keyhintlabel_for_dash">_</string> <string name="more_keys_for_apostrophe">\"</string> <string name="more_keys_for_dash">_</string> - <string name="more_keys_for_bullet">♪,♥,♠,♦,♣</string> - <string name="more_keys_for_star">†,‡,★</string> - <string name="more_keys_for_plus">±</string> - <string name="more_keys_for_left_parenthesis">[,{,<</string> - <string name="more_keys_for_right_parenthesis">],},></string> + <!-- U+266A: "♪" EIGHTH NOTE + U+2665: "♥" BLACK HEART SUIT + U+2660: "♠" BLACK SPADE SUIT + U+2666: "♦" BLACK DIAMOND SUIT + U+2663: "♣" BLACK CLUB SUIT --> + <string name="more_keys_for_bullet">♪,♥,♠,♦,♣</string> + <!-- U+2020: "†" DAGGER + U+2021: "‡" DOUBLE DAGGER + U+2605: "★" BLACK STAR --> + <string name="more_keys_for_star">†,‡,★</string> + <!-- U+00B1: "±" PLUS-MINUS SIGN --> + <string name="more_keys_for_plus">±</string> + <!-- The all letters need to be mirrored are found at + http://www.unicode.org/Public/6.1.0/ucd/BidiMirroring.txt --> + <!-- U+0028: "(" LEFT PARENTHESIS --> + <integer name="keycode_for_left_parenthesis">0x0028</integer> + <!-- U+0029: ")" RIGHT PARENTHESIS --> + <integer name="keycode_for_right_parenthesis">0x0029</integer> + <string name="more_keys_for_left_parenthesis">!fixedColumnOrder!3,<,{,[</string> + <string name="more_keys_for_right_parenthesis">!fixedColumnOrder!3,>,},]</string> + <!-- U+003C: "<" LESS-THAN SIGN --> + <integer name="keycode_for_less_than">0x003C</integer> + <!-- U+003E: ">" GREATER-THAN SIGN --> + <integer name="keycode_for_greater_than">0x003E</integer> + <!-- U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK + U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + U+2264: "≤" LESS-THAN OR EQUAL TO + U+2265: "≥" GREATER-THAN EQUAL TO + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + The following characters don't need BIDI mirroring. + U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <string name="more_keys_for_less_than">!fixedColumnOrder!3,‹,≤,«</string> + <string name="more_keys_for_greater_than">!fixedColumnOrder!3,›,≥,»</string> + <!-- U+005B: "[" LEFT SQUARE BRACKET --> + <integer name="keycode_for_left_square_bracket">0x005B</integer> + <!-- U+005D: "]" RIGHT SQUARE BRACKET --> + <integer name="keycode_for_right_square_bracket">0x005D</integer> + <!-- U+007B: "{" LEFT CURLY BRACKET --> + <integer name="keycode_for_left_curly_bracket">0x007B</integer> + <!-- U+007D: "}" RIGHT CURLY BRACKET --> + <integer name="keycode_for_right_curly_bracket">0x007D</integer> + <string name="more_keys_for_single_quote">!fixedColumnOrder!4,‘,’,‚,‛</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. --> + <!-- <string name="more_keys_for_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»</string> --> + <string name="more_keys_for_double_quote">!fixedColumnOrder!4,“,”,«,»</string> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. --> + <!-- <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!6,“,”,„,‟,«,»,‘,’,‚,‛</string> --> + <string name="more_keys_for_tablet_double_quote">!fixedColumnOrder!4,“,”,«,»,‘,’,‚,‛</string> </resources> diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index aefaec9ef..74c68464c 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -19,32 +19,30 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Symbols that are suggested between words --> - <string name="suggested_punctuations">!?,:;\u0022()\u0027-/@_</string> - <!-- Symbols that should be swapped with a magic space --> - <string name="magic_space_swapping_symbols">.,;:!?)]}\u0022</string> - <!-- Symbols that should strip a magic space --> - <string name="magic_space_stripping_symbols">\u0009\u0020\n/_\u0027-</string> - <!-- Symbols that should convert magic spaces into real space --> - <string name="magic_space_promoting_symbols">([*&@{<>+=|</string> + <string name="suggested_punctuations">!,?,\\,,:,;,\",(,),\',-,/,@,_</string> + <!-- Symbols that should be swapped with a weak space --> + <string name="weak_space_swapping_symbols">.,;:!?)]}\"</string> + <!-- Symbols that should strip a weak space --> + <string name="weak_space_stripping_symbols">"	 \n/_\'-"</string> + <!-- Symbols that should convert weak spaces into real space --> + <string name="phantom_space_promoting_symbols">([*&@{<>+=|</string> <!-- Symbols that do NOT separate words --> - <string name="symbols_excluded_from_word_separators">\u0027-</string> + <string name="symbols_excluded_from_word_separators">\'-</string> <!-- Word separator list is the union of all symbols except those that are not separators: - magic_space_swapping_symbols | magic_space_stripping_symbols | - magic_space_neutral_symbols \ symbols_excluded_from_word_separators --> + weak_space_swapping_symbols | weak_space_stripping_symbols + \ symbols_excluded_from_word_separators --> <!-- Symbol characters list that should switch back to the main layout --> - <!-- \u0022: Quotation mark (double quotation mark) - \u0027: Apostrophe (single quotation mark) - \u2018: Left single quotation mark - \u2019: Right single quotation mark - \u201a: Single low-9 quotation mark - \u201b: Single high-reversed-9 quotation mark - \u201c: Left double quotation mark - \u201d: Right double quotation mark - \u201e: Double low-9 quotation mark - \u201f: Double high-reversed-9 quotation mark - \u00ab: Left-pointing double angle quotation mark - \u00bb: Right-pointing double angle quotation mark --> - <!-- string name="layout_switch_back_symbols">\u0022\u0027\u2018\u2019\u201a\u201b\u201c\u201d\u201e\u201f\u00ab\u00bb</string> --> + <!-- U+2018: "‘" LEFT SINGLE QUOTATION MARK + U+2019: "’" RIGHT SINGLE QUOTATION MARK + U+201A: "‚" SINGLE LOW-9 QUOTATION MARK + U+201B: "‛" SINGLE HIGH-REVERSED-9 QUOTATION MARK + U+201C: "“" LEFT DOUBLE QUOTATION MARK + U+201D: "”" RIGHT DOUBLE QUOTATION MARK + U+201E: "„" DOUBLE LOW-9 QUOTATION MARK + U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK + U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK --> + <!-- <string name="layout_switch_back_symbols">\"\'‘’‚‛“”„‟«»</string> --> <string name="layout_switch_back_symbols"></string> <!-- Label for "switch to more symbol" modifier key. Must be short to fit on key! --> @@ -57,7 +55,13 @@ <!-- Label for "switch to phone numeric" key. Must be short to fit on key! --> <string name="label_to_phone_numeric_key">123</string> <!-- Label for "switch to phone symbols" key. Must be short to fit on key! --> - <string name="label_to_phone_symbols_key">\uff0a\uff03</string> + <!-- U+FF0A: "*" FULLWIDTH ASTERISK + U+FF03: "#" FULLWIDTH NUMBER SIGN --> + <string name="label_to_phone_symbols_key">*#</string> + <!-- Key label for "ante meridiem" --> + <string name="label_time_am">"AM"</string> + <!-- Key label for "post meridiem" --> + <string name="label_time_pm">"PM"</string> <!-- Always show the suggestion strip --> <string name="prefs_suggestion_visibility_show_value">0</string> @@ -120,6 +124,7 @@ <!-- Title for Latin keyboard debug settings activity / dialog --> <string name="english_ime_debug_settings">Android keyboard Debug settings</string> <string name="prefs_debug_mode">Debug Mode</string> + <string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string> <!-- Keyboard theme names --> <string name="layout_basic">Basic</string> @@ -161,9 +166,12 @@ <!-- Generic subtype label --> <string name="subtype_generic">%s</string> + <!-- Description for generic QWERTY keyboard subtype --> + <string name="subtype_generic_qwerty">%s (QWERTY)</string> <!-- dictionary pack package name /settings activity (for shared prefs and settings) --> <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string> <string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string> <string name="settings_ms">ms</string> + <string name="settings_warning_researcher_mode">Attention! You are using the special keyboard for research purposes.</string> </resources> diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml index f767cb349..44fc2b9c1 100644 --- a/java/res/values/keyboard-icons-black.xml +++ b/java/res/values/keyboard-icons-black.xml @@ -30,10 +30,11 @@ <item name="iconTabKey">@drawable/sym_bkeyboard_tab</item> <item name="iconShortcutKey">@drawable/sym_bkeyboard_mic</item> <item name="iconShortcutForLabel">@drawable/sym_bkeyboard_label_mic</item> - <item name="iconShiftedShiftKey">@drawable/sym_bkeyboard_shift_locked</item> + <item name="iconSpaceKeyForNumberLayout">@drawable/sym_bkeyboard_space</item> + <item name="iconShiftKeyShifted">@drawable/sym_bkeyboard_shift_locked</item> + <item name="iconDisabledShortcutKey">@drawable/sym_bkeyboard_voice_off</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> - <!-- LatinKeyboard icons --> - <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> - <item name="disabledShortcutIcon">@drawable/sym_bkeyboard_voice_off</item> + <!-- TODO: Needs dedicated black theme globe icon --> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml index f1021433d..5fba0253d 100644 --- a/java/res/values/keyboard-icons-ics.xml +++ b/java/res/values/keyboard-icons-ics.xml @@ -23,16 +23,16 @@ <item name="iconShiftKey">@drawable/sym_keyboard_shift_holo</item> <item name="iconDeleteKey">@drawable/sym_keyboard_delete_holo</item> <item name="iconSettingsKey">@drawable/sym_keyboard_settings_holo</item> - <item name="iconSpaceKey">@drawable/sym_keyboard_space_holo</item> + <item name="iconSpaceKey">@null</item> <item name="iconReturnKey">@drawable/sym_keyboard_return_holo</item> <item name="iconSearchKey">@drawable/sym_keyboard_search_holo</item> <item name="iconTabKey">@drawable/sym_keyboard_tab_holo</item> <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo</item> <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo</item> - <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked_holo</item> + <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo</item> + <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo</item> + <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> - <!-- LatinKeyboard icons --> - <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> - <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml index 07ece66b1..837b1a37a 100644 --- a/java/res/values/keyboard-icons-white.xml +++ b/java/res/values/keyboard-icons-white.xml @@ -26,10 +26,11 @@ <item name="iconTabKey">@drawable/sym_keyboard_tab</item> <item name="iconShortcutKey">@drawable/sym_keyboard_mic</item> <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic</item> - <item name="iconShiftedShiftKey">@drawable/sym_keyboard_shift_locked</item> + <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space</item> + <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked</item> + <!-- TODO: Needs non-holo disabled shortcut icon drawable --> + <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> - <!-- LatinKeyboard icons --> - <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> - <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index 59cc07531..d3d9b6324 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -21,11 +21,17 @@ <resources> <!-- These code should be aligned with Keyboard.CODE_*. --> <integer name="key_tab">9</integer> - <integer name="key_return">10</integer> + <integer name="key_enter">10</integer> <integer name="key_space">32</integer> <integer name="key_shift">-1</integer> <integer name="key_switch_alpha_symbol">-2</integer> - <integer name="key_delete">-5</integer> - <integer name="key_settings">-6</integer> - <integer name="key_shortcut">-7</integer> + <integer name="key_output_text">-3</integer> + <integer name="key_delete">-4</integer> + <integer name="key_settings">-5</integer> + <integer name="key_shortcut">-6</integer> + <integer name="key_action_enter">-7</integer> + <integer name="key_action_next">-8</integer> + <integer name="key_action_previous">-9</integer> + <integer name="key_language_switch">-10</integer> + <integer name="key_unspecified">-11</integer> </resources> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index e00547a62..f2c02d014 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -20,22 +20,26 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Title for Latin keyboard --> <string name="english_ime_name">Android keyboard</string> + <!-- Application name for opensource Android keyboard. AOSP(Android Open Source Project) should not be translated. --> + <string name="aosp_android_keyboard_ime_name">Android keyboard (AOSP)</string> <!-- Title for Latin keyboard settings activity / dialog --> <string name="english_ime_settings">Android keyboard settings</string> <!-- Title for Latin keyboard input options dialog [CHAR LIMIT=25] --> <string name="english_ime_input_options">Input options</string> - <!-- Title for Latin Keyboard spell checker service --> - <string name="spell_checker_service_name">Android correction</string> + <!-- Name of Android spell checker service --> + <string name="spell_checker_service_name">Android spell checker</string> + <!-- Name of Android spell checker service. AOSP(Android Open Source Project) should not be translated. --> + <string name="aosp_spell_checker_service_name">Android spell checker (AOSP)</string> <!-- Title for the spell checking service settings screen --> <string name="android_spell_checker_settings">Spell checking settings</string> - <!-- Title for the "use proximity" option for spell checking [CHAR LIMIT=25] --> - <string name="use_proximity_option_title">Use proximity data</string> + <!-- Title for the spell checker option to turn on/off contact names lookup [CHAR LIMIT=25] --> + <string name="use_contacts_for_spellchecking_option_title">Look up contact names</string> - <!-- Description for the "use proximity" option for spell checking [CHAR LIMIT=65] --> - <string name="use_proximity_option_summary">Use a keyboard-like proximity algorithm for spell checking</string> + <!-- Description for the spell checker option to turn on/off contact names lookup. [CHAR LIMIT=65] --> + <string name="use_contacts_for_spellchecking_option_summary">Spell checker uses entries from your contact list</string> <!-- Option to provide vibrate/haptic feedback on keypress --> <string name="vibrate_on_keypress">Vibrate on keypress</string> @@ -58,7 +62,14 @@ <!-- Option name for advanced settings screen [CHAR LIMIT=25] --> <string name="advanced_settings">Advanced settings</string> <!-- Option summary for advanced settings screen [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] --> - <string name="advanced_settings_summary">Options for expert users</string> + <string name="advanced_settings_summary">Options for experts</string> + + <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=25] --> + <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string> + <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] --> + <string name="include_other_imes_in_language_switch_list_summary">Language switch key covers other input methods too</string> + <!-- Option to suppress language switch key [CHAR LIMIT=25] --> + <string name="suppress_language_switch_key">Suppress language switch key</string> <!-- Option for the dismiss delay of the key popup [CHAR LIMIT=25] --> <string name="key_preview_popup_dismiss_delay">Key popup dismiss delay</string> @@ -93,9 +104,6 @@ <string name="prefs_suggestion_visibility_show_only_portrait_name">Show on portrait mode</string> <string name="prefs_suggestion_visibility_hide_name">Always hide</string> - <!-- Option to show/hide the settings key --> - <string name="prefs_settings_key">Show settings key</string> - <!-- Option to decide the auto correction threshold score --> <!-- Option to enable auto correction [CHAR LIMIT=20]--> <string name="auto_correction">Auto correction</string> @@ -126,6 +134,8 @@ <string name="label_go_key">Go</string> <!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! [CHAR LIMIT=5] --> <string name="label_next_key">Next</string> + <!-- Label for soft enter key when it performs PREVIOUS action. Must be short to fit on key! [CHAR LIMIT=5] --> + <string name="label_previous_key">Prev</string> <!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! [CHAR LIMIT=5] --> <string name="label_done_key">Done</string> <!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! [CHAR LIMIT=5] --> @@ -152,12 +162,12 @@ <!-- Spoken description for unknown keyboard keys. --> <string name="spoken_description_unknown">Key code %d</string> - <!-- Spoken description for the "Shift" keyboard key. --> + <!-- Spoken description for the "Shift" keyboard key when "Shift" is off. --> <string name="spoken_description_shift">Shift</string> - <!-- Spoken description for the "Shift" keyboard key's pressed state. --> - <string name="spoken_description_shift_shifted">Shift enabled</string> - <!-- Spoken description for the "Shift" keyboard key's pressed state. --> - <string name="spoken_description_caps_lock">Caps lock enabled</string> + <!-- Spoken description for the "Shift" keyboard key when "Shift" is on. --> + <string name="spoken_description_shift_shifted">Shift on (tap to disable)</string> + <!-- Spoken description for the "Shift" keyboard key when "Caps lock" is on. --> + <string name="spoken_description_caps_lock">Caps lock on (tap to disable)</string> <!-- Spoken description for the "Delete" keyboard key. --> <string name="spoken_description_delete">Delete</string> <!-- Spoken description for the "To Symbol" keyboard key. --> @@ -178,47 +188,24 @@ <string name="spoken_description_smiley">Smiley face</string> <!-- Spoken description for the "Return" keyboard key. --> <string name="spoken_description_return">Return</string> - - <!-- Spoken description for the "," keyboard key. --> - <string name="spoken_description_comma">Comma</string> - <!-- Spoken description for the "." keyboard key. --> - <string name="spoken_description_period">Period</string> - <!-- Spoken description for the "(" keyboard key. --> - <string name="spoken_description_left_parenthesis">Left parenthesis</string> - <!-- Spoken description for the ")" keyboard key. --> - <string name="spoken_description_right_parenthesis">Right parenthesis</string> - <!-- Spoken description for the ":" keyboard key. --> - <string name="spoken_description_colon">Colon</string> - <!-- Spoken description for the ";" keyboard key. --> - <string name="spoken_description_semicolon">Semicolon</string> - <!-- Spoken description for the "!" keyboard key. --> - <string name="spoken_description_exclamation_mark">Exclamation mark</string> - <!-- Spoken description for the "?" keyboard key. --> - <string name="spoken_description_question_mark">Question mark</string> - <!-- Spoken description for the """ keyboard key. --> - <string name="spoken_description_double_quote">Double quote</string> - <!-- Spoken description for the "'" keyboard key. --> - <string name="spoken_description_single_quote">Single quote</string> - <!-- Spoken description for the "\u2022" (BULLET) keyboard key. --> + <!-- Spoken description for the "U+2022" (BULLET) keyboard key. --> <string name="spoken_description_dot">Dot</string> - <!-- Spoken description for the "\u221a" (SQUARE ROOT) keyboard key. --> - <string name="spoken_description_square_root">Square root</string> - <!-- Spoken description for the "\u03C0" (GREEK SMALL LETTER PI) keyboard key. --> - <string name="spoken_description_pi">Pi</string> - <!-- Spoken description for the "\u0394" (GREEK CAPITAL LETTER DELTA) keyboard key. --> - <string name="spoken_description_delta">Delta</string> - <!-- Spoken description for the "\u2122" (TRADE MARK SIGN) keyboard key. --> - <string name="spoken_description_trademark">Trademark</string> - <!-- Spoken description for the "\u2105" (CARE OF) keyboard key. --> - <string name="spoken_description_care_of">Care of</string> - <!-- Spoken description for the "*" keyboard key. --> - <string name="spoken_description_star">Star</string> - <!-- Spoken description for the "#" keyboard key. --> - <string name="spoken_description_pound">Pound</string> - <!-- Spoken description for the "\u2026" (HORIZONTAL ELLIPSIS) keyboard key. --> - <string name="spoken_description_ellipsis">Ellipsis</string> - <!-- Spoken description for the "\u201E" (DOUBLE LOW-9 QUOTATION MARK) keyboard key. --> - <string name="spoken_description_low_double_quote">Low double quote</string> + + <!-- Spoken feedback after turning "Shift" mode on. --> + <string name="spoken_description_shiftmode_on">Shift enabled</string> + <!-- Spoken feedback after turning "Caps lock" mode on. --> + <string name="spoken_description_shiftmode_locked">Caps lock enabled</string> + <!-- Spoken feedback after turning "Shift" mode off. --> + <string name="spoken_description_shiftmode_off">Shift disabled</string> + + <!-- Spoken feedback after changing to the symbols keyboard. --> + <string name="spoken_description_mode_symbol">Symbols mode</string> + <!-- Spoken feedback after changing to the alphanumeric keyboard. --> + <string name="spoken_description_mode_alpha">Letters mode</string> + <!-- Spoken feedback after changing to the phone dialer keyboard. --> + <string name="spoken_description_mode_phone">Phone mode</string> + <!-- Spoken feedback after changing to the shifted phone dialer (symbols) keyboard. --> + <string name="spoken_description_mode_phone_shift">Phone symbols mode</string> <!-- Voice related labels --> @@ -320,7 +307,7 @@ <string name="select_language">Input languages</string> <!-- Add to dictionary hint --> - <string name="hint_add_to_dictionary">\u2190 Touch again to save</string> + <string name="hint_add_to_dictionary">← Touch again to save</string> <!-- Inform the user that a particular language has an available dictionary --> <string name="has_dictionary">Dictionary available</string> @@ -333,8 +320,6 @@ <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]--> <string name="keyboard_layout">Keyboard theme</string> - <!-- Description for German QWERTY keyboard subtype [CHAR LIMIT=22] --> - <string name="subtype_de_qwerty">German QWERTY</string> <!-- Description for English (United Kingdom) keyboard subtype [CHAR LIMIT=22] --> <string name="subtype_en_GB">English (UK)</string> <!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] --> diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml index 43aa58388..7d8b7ddf2 100644 --- a/java/res/values/styles.xml +++ b/java/res/values/styles.xml @@ -17,13 +17,14 @@ <resources> <!-- Theme "Basic" --> <style name="Keyboard"> + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">0</item> <item name="touchPositionCorrectionData">@array/touch_position_correction_data_empty</item> <item name="rowHeight">25%p</item> <item name="keyboardHeight">@dimen/keyboardHeight</item> <item name="maxKeyboardHeight">@fraction/maxKeyboardHeight</item> <item name="minKeyboardHeight">@fraction/minKeyboardHeight</item> - <item name="moreKeysTemplate">@xml/kbd_mini_keyboard_template</item> + <item name="moreKeysTemplate">@xml/kbd_more_keys_keyboard_template</item> <item name="keyboardTopPadding">@fraction/keyboard_top_padding</item> <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding</item> <item name="keyboardHorizontalEdgesPadding">@fraction/keyboard_horizontal_edges_padding</item> @@ -31,12 +32,6 @@ <item name="verticalGap">@fraction/key_bottom_gap</item> <item name="maxMoreKeysColumn">@integer/config_max_more_keys_column</item> </style> - <style name="LatinKeyboard"> - <item name="autoCorrectionSpacebarLedEnabled">@bool/config_auto_correction_spacebar_led_enabled - </item> - <item name="spacebarTextColor">#FFC0C0C0</item> - <item name="spacebarTextShadowColor">#80000000</item> - </style> <style name="KeyboardView"> <item name="android:background">@drawable/keyboard_background</item> <item name="keyBackground">@drawable/btn_keyboard_key</item> @@ -45,18 +40,18 @@ <item name="keyLabelRatio">@fraction/key_label_ratio</item> <item name="keyHintLetterRatio">@fraction/key_hint_letter_ratio</item> <item name="keyHintLabelRatio">@fraction/key_hint_label_ratio</item> - <item name="keyUppercaseLetterRatio">@fraction/key_uppercase_letter_ratio</item> + <item name="keyShiftedLetterHintRatio">@fraction/key_uppercase_letter_ratio</item> <item name="keyTextStyle">normal</item> <item name="keyTextColor">#FFFFFFFF</item> <item name="keyTextInactivatedColor">#FFFFFFFF</item> <item name="keyHintLetterColor">#80000000</item> <item name="keyHintLabelColor">#E0E0E4E5</item> - <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item> - <item name="keyUppercaseLetterActivatedColor">#CCE0E4E5</item> + <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item> + <item name="keyShiftedLetterHintActivatedColor">#CCE0E4E5</item> <item name="keyLabelHorizontalPadding">@dimen/key_label_horizontal_padding</item> <item name="keyHintLetterPadding">@dimen/key_hint_letter_padding</item> <item name="keyPopupHintLetterPadding">@dimen/key_popup_hint_letter_padding</item> - <item name="keyUppercaseLetterPadding">@dimen/key_uppercase_letter_padding</item> + <item name="keyShiftedLetterHintPadding">@dimen/key_uppercase_letter_padding</item> <item name="keyPreviewLayout">@layout/key_preview</item> <item name="keyPreviewBackground">@drawable/keyboard_key_feedback</item> <item name="keyPreviewLeftBackground">@null</item> @@ -65,14 +60,39 @@ <item name="keyPreviewOffset">@dimen/key_preview_offset</item> <item name="keyPreviewHeight">@dimen/key_preview_height</item> <item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item> - <item name="moreKeysLayout">@layout/mini_keyboard</item> + <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item> + <item name="moreKeysLayout">@layout/more_keys_keyboard</item> <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item> <item name="shadowColor">#BB000000</item> <item name="shadowRadius">2.75</item> - <item name="backgroundDimAmount">0.5</item> + <item name="backgroundDimAlpha">128</item> + <!-- Common attributes of LatinKeyboardView --> + <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> + <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> + <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item> + <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item> + <item name="keyRepeatStartTimeout">@integer/config_key_repeat_start_timeout</item> + <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item> + <item name="longPressKeyTimeout">@integer/config_long_press_key_timeout</item> + <item name="longPressShiftKeyTimeout">@integer/config_long_press_shift_key_timeout</item> + <item name="longPressSpaceKeyTimeout">@integer/config_long_press_space_key_timeout</item> + <item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item> + <item name="showMoreKeysKeyboardAtTouchedPoint">@bool/config_show_more_keys_keyboard_at_touched_point</item> + <item name="languageOnSpacebarFadeoutAnimator">@anim/language_on_spacebar_fadeout</item> + <item name="altCodeKeyWhileTypingFadeoutAnimator">@anim/alt_code_key_while_typing_fadeout</item> + <item name="altCodeKeyWhileTypingFadeinAnimator">@anim/alt_code_key_while_typing_fadein</item> </style> <style - name="MiniKeyboard" + name="LatinKeyboardView" + parent="KeyboardView"> + <item name="autoCorrectionSpacebarLedEnabled">true</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FFC0C0C0</item> + <item name="spacebarTextShadowColor">#80000000</item> + </style> + <style + name="MoreKeysKeyboard" parent="Keyboard" > <item name="keyboardTopPadding">0dip</item> @@ -80,16 +100,16 @@ <item name="horizontalGap">0dip</item> </style> <style - name="MiniKeyboardView" + name="MoreKeysKeyboardView" parent="KeyboardView" > <item name="keyBackground">@drawable/btn_keyboard_key_popup</item> - <item name="verticalCorrection">@dimen/mini_keyboard_vertical_correction</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction</item> </style> - <style name="MiniKeyboardPanelStyle"> + <style name="MoreKeysKeyboardPanelStyle"> <item name="android:background">@drawable/keyboard_popup_panel_background</item> - <item name="android:paddingLeft">@dimen/mini_keyboard_horizontal_edges_padding</item> - <item name="android:paddingRight">@dimen/mini_keyboard_horizontal_edges_padding</item> + <item name="android:paddingLeft">@dimen/more_keys_keyboard_horizontal_edges_padding</item> + <item name="android:paddingRight">@dimen/more_keys_keyboard_horizontal_edges_padding</item> </style> <style name="SuggestionsStripBackgroundStyle"> <item name="android:background">@drawable/keyboard_suggest_strip</item> @@ -98,7 +118,8 @@ name="SuggestionsViewStyle" parent="SuggestionsStripBackgroundStyle" > - <item name="suggestionStripOption">autoCorrectBold</item> + <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> + <item name="colorValidTypedWord">#FFFCAE00</item> <item name="colorTypedWord">@android:color/white</item> <item name="colorAutoCorrect">#FFFCAE00</item> <item name="colorSuggested">#FFFCAE00</item> @@ -110,7 +131,7 @@ </style> <style name="MoreSuggestionsViewStyle" - parent="MiniKeyboardView" + parent="MoreKeysKeyboardView" > </style> <style name="SuggestionBackgroundStyle"> @@ -124,6 +145,7 @@ name="Keyboard.HighContrast" parent="Keyboard" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">1</item> </style> <style @@ -133,11 +155,22 @@ <item name="android:background">@android:color/black</item> <item name="keyBackground">@drawable/btn_keyboard_key3</item> </style> + <style + name="LatinKeyboardView.HighContrast" + parent="KeyboardView.HighContrast" + > + <item name="autoCorrectionSpacebarLedEnabled">true</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FFC0C0C0</item> + <item name="spacebarTextShadowColor">#80000000</item> + </style> <!-- Theme "Stone" --> <style name="Keyboard.Stone" parent="Keyboard" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">6</item> <item name="keyboardHeight">@dimen/keyboardHeight_stone</item> <item name="keyboardTopPadding">@fraction/keyboard_top_padding_stone</item> @@ -146,13 +179,6 @@ <item name="verticalGap">@fraction/key_bottom_gap_stone</item> </style> <style - name="LatinKeyboard.Stone" - parent="LatinKeyboard" - > - <item name="spacebarTextColor">#FF000000</item> - <item name="spacebarTextShadowColor">#D0FFFFFF</item> - </style> - <style name="KeyboardView.Stone" parent="KeyboardView" > @@ -161,12 +187,22 @@ <item name="keyTextInactivatedColor">#FF808080</item> <item name="keyHintLetterColor">#80000000</item> <item name="keyHintLabelColor">#E0000000</item> - <item name="keyUppercaseLetterInactivatedColor">#66000000</item> - <item name="keyUppercaseLetterActivatedColor">#CC000000</item> + <item name="keyShiftedLetterHintInactivatedColor">#66000000</item> + <item name="keyShiftedLetterHintActivatedColor">#CC000000</item> <item name="shadowColor">#FFFFFFFF</item> </style> <style - name="MiniKeyboard.Stone" + name="LatinKeyboardView.Stone" + parent="KeyboardView.Stone" + > + <item name="autoCorrectionSpacebarLedEnabled">true</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FF000000</item> + <item name="spacebarTextShadowColor">#D0FFFFFF</item> + </style> + <style + name="MoreKeysKeyboard.Stone" parent="Keyboard.Stone" > <item name="keyboardTopPadding">0dip</item> @@ -174,8 +210,8 @@ <item name="horizontalGap">0dip</item> </style> <style - name="MiniKeyboardView.Stone" - parent="MiniKeyboardView" + name="MoreKeysKeyboardView.Stone" + parent="MoreKeysKeyboardView" > <item name="keyBackground">@drawable/btn_keyboard_key_stone</item> <item name="keyTextColor">#FF000000</item> @@ -186,6 +222,7 @@ name="Keyboard.Stone.Bold" parent="Keyboard.Stone" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">7</item> </style> <style @@ -194,11 +231,22 @@ > <item name="keyTextStyle">bold</item> </style> + <style + name="LatinKeyboardView.Stone.Bold" + parent="KeyboardView.Stone.Bold" + > + <item name="autoCorrectionSpacebarLedEnabled">true</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FF000000</item> + <item name="spacebarTextShadowColor">#D0FFFFFF</item> + </style> <!-- Theme "Gingerbread" --> <style name="Keyboard.Gingerbread" parent="Keyboard" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">8</item> <item name="touchPositionCorrectionData">@array/touch_position_correction_data_gingerbread</item> <item name="horizontalGap">@fraction/key_horizontal_gap_gb</item> @@ -213,7 +261,17 @@ <item name="keyTextStyle">bold</item> </style> <style - name="MiniKeyboard.Gingerbread" + name="LatinKeyboardView.Gingerbread" + parent="KeyboardView.Gingerbread" + > + <item name="autoCorrectionSpacebarLedEnabled">true</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FFC0C0C0</item> + <item name="spacebarTextShadowColor">#80000000</item> + </style> + <style + name="MoreKeysKeyboard.Gingerbread" parent="Keyboard.Gingerbread" > <item name="keyboardTopPadding">0dip</item> @@ -221,8 +279,8 @@ <item name="horizontalGap">0dip</item> </style> <style - name="MiniKeyboardView.Gingerbread" - parent="MiniKeyboardView" + name="MoreKeysKeyboardView.Gingerbread" + parent="MoreKeysKeyboardView" > <item name="android:background">@null</item> </style> @@ -231,6 +289,7 @@ name="Keyboard.IceCreamSandwich" parent="Keyboard" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">5</item> <item name="keyboardTopPadding">@fraction/keyboard_top_padding_ics</item> <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_ics</item> @@ -239,12 +298,6 @@ <item name="touchPositionCorrectionData">@array/touch_position_correction_data_ice_cream_sandwich</item> </style> <style - name="LatinKeyboard.IceCreamSandwich" - parent="LatinKeyboard" - > - <item name="disabledShortcutIcon">@drawable/sym_keyboard_voice_off_holo</item> - </style> - <style name="KeyboardView.IceCreamSandwich" parent="KeyboardView" > @@ -254,8 +307,8 @@ <item name="keyTextInactivatedColor">#66E0E4E5</item> <item name="keyHintLetterColor">#80000000</item> <item name="keyHintLabelColor">#A0FFFFFF</item> - <item name="keyUppercaseLetterInactivatedColor">#66E0E4E5</item> - <item name="keyUppercaseLetterActivatedColor">#FFFFFFFF</item> + <item name="keyShiftedLetterHintInactivatedColor">#66E0E4E5</item> + <item name="keyShiftedLetterHintActivatedColor">#FFFFFFFF</item> <item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item> <item name="keyPreviewLeftBackground">@drawable/keyboard_key_feedback_left_ics</item> <item name="keyPreviewRightBackground">@drawable/keyboard_key_feedback_right_ics</item> @@ -268,7 +321,17 @@ <item name="shadowRadius">0.0</item> </style> <style - name="MiniKeyboard.IceCreamSandwich" + name="LatinKeyboardView.IceCreamSandwich" + parent="KeyboardView.IceCreamSandwich" + > + <item name="autoCorrectionSpacebarLedEnabled">false</item> + <item name="autoCorrectionSpacebarLedIcon">@drawable/sym_keyboard_space_led_holo</item> + <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item> + <item name="spacebarTextColor">#FFC0C0C0</item> + <item name="spacebarTextShadowColor">#80000000</item> + </style> + <style + name="MoreKeysKeyboard.IceCreamSandwich" parent="Keyboard.IceCreamSandwich" > <item name="keyboardTopPadding">0dip</item> @@ -276,16 +339,17 @@ <item name="horizontalGap">0dip</item> </style> <style - name="MiniKeyboardView.IceCreamSandwich" - parent="MiniKeyboardView" + name="MoreKeysKeyboardView.IceCreamSandwich" + parent="MoreKeysKeyboardView" > <item name="android:background">@null</item> <item name="keyBackground">@drawable/btn_keyboard_key_popup_ics</item> + <item name="verticalCorrection">@dimen/more_keys_keyboard_vertical_correction_ics</item> </style> - <style name="MiniKeyboardPanelStyle.IceCreamSandwich"> + <style name="MoreKeysKeyboardPanelStyle.IceCreamSandwich"> <item name="android:background">@drawable/keyboard_popup_panel_background_holo</item> - <item name="android:paddingLeft">@dimen/mini_keyboard_horizontal_edges_padding_ics</item> - <item name="android:paddingRight">@dimen/mini_keyboard_horizontal_edges_padding_ics</item> + <item name="android:paddingLeft">@dimen/more_keys_keyboard_horizontal_edges_padding_ics</item> + <item name="android:paddingRight">@dimen/more_keys_keyboard_horizontal_edges_padding_ics</item> </style> <style name="SuggestionsStripBackgroundStyle.IceCreamSandwich"> <item name="android:background">@drawable/keyboard_suggest_strip_holo</item> @@ -296,11 +360,12 @@ > <item name="suggestionStripOption">autoCorrectBold|validTypedWordBold</item> <!-- android:color/holo_blue_light=#FF33B5E5 --> + <item name="colorValidTypedWord">@android:color/holo_blue_light</item> <item name="colorTypedWord">@android:color/holo_blue_light</item> <item name="colorAutoCorrect">@android:color/holo_blue_light</item> <item name="colorSuggested">@android:color/holo_blue_light</item> + <item name="alphaValidTypedWord">85</item> <item name="alphaTypedWord">85</item> - <item name="alphaAutoCorrect">100</item> <item name="alphaSuggested">70</item> <item name="alphaObsoleted">70</item> <item name="suggestionsCountInStrip">@integer/suggestions_count_in_strip</item> @@ -310,7 +375,7 @@ </style> <style name="MoreSuggestionsViewStyle.IceCreamSandwich" - parent="MiniKeyboardView.IceCreamSandwich" + parent="MoreKeysKeyboardView.IceCreamSandwich" > </style> <style name="SuggestionBackgroundStyle.IceCreamSandwich"> @@ -318,11 +383,11 @@ </style> <style name="SuggestionPreviewBackgroundStyle.IceCreamSandwich" - parent="MiniKeyboardPanelStyle.IceCreamSandwich" + parent="MoreKeysKeyboardPanelStyle.IceCreamSandwich" > </style> - <style name="MiniKeyboardAnimation"> - <item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item> - <item name="android:windowExitAnimation">@anim/mini_keyboard_fadeout</item> + <style name="MoreKeysKeyboardAnimation"> + <item name="android:windowEnterAnimation">@anim/more_keys_keyboard_fadein</item> + <item name="android:windowExitAnimation">@anim/more_keys_keyboard_fadeout</item> </style> </resources> diff --git a/java/res/values/themes-basic-highcontrast.xml b/java/res/values/themes-basic-highcontrast.xml index abb7c8057..19df42ce1 100644 --- a/java/res/values/themes-basic-highcontrast.xml +++ b/java/res/values/themes-basic-highcontrast.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme.HighContrast" parent="KeyboardIcons"> <item name="keyboardStyle">@style/Keyboard.HighContrast</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard</item> <item name="keyboardViewStyle">@style/KeyboardView.HighContrast</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.HighContrast</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item> diff --git a/java/res/values/themes-basic.xml b/java/res/values/themes-basic.xml index ff9fed55f..5d477206d 100644 --- a/java/res/values/themes-basic.xml +++ b/java/res/values/themes-basic.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme" parent="KeyboardIcons"> <item name="keyboardStyle">@style/Keyboard</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard</item> <item name="keyboardViewStyle">@style/KeyboardView</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item> diff --git a/java/res/values/themes-gingerbread.xml b/java/res/values/themes-gingerbread.xml index be853eb0f..a13979818 100644 --- a/java/res/values/themes-gingerbread.xml +++ b/java/res/values/themes-gingerbread.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme.Gingerbread" parent="KeyboardIcons"> <item name="keyboardStyle">@style/Keyboard.Gingerbread</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard</item> <item name="keyboardViewStyle">@style/KeyboardView.Gingerbread</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard.Gingerbread</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Gingerbread</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Gingerbread</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Gingerbread</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Gingerbread</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item> diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml index 618aaed79..e6fd4f451 100644 --- a/java/res/values/themes-ics.xml +++ b/java/res/values/themes-ics.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme.IceCreamSandwich" parent="KeyboardIcons.IceCreamSandwich"> <item name="keyboardStyle">@style/Keyboard.IceCreamSandwich</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard.IceCreamSandwich</item> <item name="keyboardViewStyle">@style/KeyboardView.IceCreamSandwich</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard.IceCreamSandwich</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView.IceCreamSandwich</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle.IceCreamSandwich</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.IceCreamSandwich</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.IceCreamSandwich</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.IceCreamSandwich</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle.IceCreamSandwich</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle.IceCreamSandwich</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle.IceCreamSandwich</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle.IceCreamSandwich</item> diff --git a/java/res/values/themes-stone-bold.xml b/java/res/values/themes-stone-bold.xml index 532a2985e..47de99e47 100644 --- a/java/res/values/themes-stone-bold.xml +++ b/java/res/values/themes-stone-bold.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme.Stone.Bold" parent="KeyboardIcons.Black"> <item name="keyboardStyle">@style/Keyboard.Stone.Bold</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item> <item name="keyboardViewStyle">@style/KeyboardView.Stone.Bold</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard.Stone</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Stone</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone.Bold</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Stone</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Stone</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item> diff --git a/java/res/values/themes-stone.xml b/java/res/values/themes-stone.xml index cb3edc58f..a0b39e3e6 100644 --- a/java/res/values/themes-stone.xml +++ b/java/res/values/themes-stone.xml @@ -17,11 +17,11 @@ <resources> <style name="KeyboardTheme.Stone" parent="KeyboardIcons.Black"> <item name="keyboardStyle">@style/Keyboard.Stone</item> - <item name="latinKeyboardStyle">@style/LatinKeyboard.Stone</item> <item name="keyboardViewStyle">@style/KeyboardView.Stone</item> - <item name="miniKeyboardStyle">@style/MiniKeyboard.Stone</item> - <item name="miniKeyboardViewStyle">@style/MiniKeyboardView.Stone</item> - <item name="miniKeyboardPanelStyle">@style/MiniKeyboardPanelStyle</item> + <item name="latinKeyboardViewStyle">@style/LatinKeyboardView.Stone</item> + <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.Stone</item> + <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.Stone</item> + <item name="moreKeysKeyboardPanelStyle">@style/MoreKeysKeyboardPanelStyle</item> <item name="suggestionsStripBackgroundStyle">@style/SuggestionsStripBackgroundStyle</item> <item name="suggestionsViewStyle">@style/SuggestionsViewStyle</item> <item name="moreSuggestionsViewStyle">@style/MoreSuggestionsViewStyle</item> diff --git a/java/res/values/touch-position-correction.xml b/java/res/values/touch-position-correction.xml index 0a0e4e545..41b435ad0 100644 --- a/java/res/values/touch-position-correction.xml +++ b/java/res/values/touch-position-correction.xml @@ -71,4 +71,4 @@ <item>0.0880847</item> <item>0.1522819</item> </string-array> -</resources>
\ No newline at end of file +</resources> diff --git a/java/res/xml-ar/keyboard_set.xml b/java/res/xml-ar/keyboard_set.xml new file mode 100644 index 000000000..7b70f633c --- /dev/null +++ b/java/res/xml-ar/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="ar" > + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_arabic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-be/keyboard_set.xml b/java/res/xml-be/keyboard_set.xml new file mode 100644 index 000000000..823234698 --- /dev/null +++ b/java/res/xml-be/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="be"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-bg/keyboard_set.xml b/java/res/xml-bg/keyboard_set.xml new file mode 100644 index 000000000..49914d54b --- /dev/null +++ b/java/res/xml-bg/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="bg"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_bulgarian" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-cs/keyboard_set.xml b/java/res/xml-cs/keyboard_set.xml new file mode 100644 index 000000000..b4535164b --- /dev/null +++ b/java/res/xml-cs/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="cs"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-da/keyboard_set.xml b/java/res/xml-da/keyboard_set.xml new file mode 100644 index 000000000..9b512ec6c --- /dev/null +++ b/java/res/xml-da/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="da"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-de-rZZ/keyboard_set.xml b/java/res/xml-de-rZZ/keyboard_set.xml new file mode 100644 index 000000000..635884d1d --- /dev/null +++ b/java/res/xml-de-rZZ/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="de"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-de/keyboard_set.xml b/java/res/xml-de/keyboard_set.xml new file mode 100644 index 000000000..485e63f06 --- /dev/null +++ b/java/res/xml-de/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="de"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-el/keyboard_set.xml b/java/res/xml-el/keyboard_set.xml new file mode 100644 index 000000000..19ecb771b --- /dev/null +++ b/java/res/xml-el/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="el"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_greek" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-es/kbd_qwerty.xml b/java/res/xml-es/kbd_qwerty.xml deleted file mode 100644 index 568f4d652..000000000 --- a/java/res/xml-es/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="es,es_US" -> - <include - latin:keyboardLayout="@xml/kbd_rows_spanish" /> -</Keyboard> diff --git a/java/res/xml-es/keyboard_set.xml b/java/res/xml-es/keyboard_set.xml new file mode 100644 index 000000000..9cf208b40 --- /dev/null +++ b/java/res/xml-es/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="es,es_US"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_spanish" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_spanish_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_spanish_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-et/keyboard_set.xml b/java/res/xml-et/keyboard_set.xml new file mode 100644 index 000000000..9ccef8c81 --- /dev/null +++ b/java/res/xml-et/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="et"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-fa/keyboard_set.xml b/java/res/xml-fa/keyboard_set.xml new file mode 100644 index 000000000..9bd105093 --- /dev/null +++ b/java/res/xml-fa/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fa" > + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_arabic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-fi/kbd_qwerty.xml b/java/res/xml-fi/kbd_qwerty.xml deleted file mode 100644 index 75721e057..000000000 --- a/java/res/xml-fi/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="fi" -> - <include - latin:keyboardLayout="@xml/kbd_rows_scandinavian" /> -</Keyboard> diff --git a/java/res/xml-fi/keyboard_set.xml b/java/res/xml-fi/keyboard_set.xml new file mode 100644 index 000000000..45968af90 --- /dev/null +++ b/java/res/xml-fi/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fi"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-fr-rCA/keyboard_set.xml b/java/res/xml-fr-rCA/keyboard_set.xml new file mode 100644 index 000000000..ea6ac8f26 --- /dev/null +++ b/java/res/xml-fr-rCA/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fr_CA"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-fr-rCH/kbd_qwerty.xml b/java/res/xml-fr-rCH/kbd_qwerty.xml deleted file mode 100644 index 41b701d83..000000000 --- a/java/res/xml-fr-rCH/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2008, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="fr_CH" -> - <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> -</Keyboard> diff --git a/java/res/xml-fr-rCH/keyboard_set.xml b/java/res/xml-fr-rCH/keyboard_set.xml new file mode 100644 index 000000000..751900b88 --- /dev/null +++ b/java/res/xml-fr-rCH/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fr_CH"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-fr/keyboard_set.xml b/java/res/xml-fr/keyboard_set.xml new file mode 100644 index 000000000..fa1339b47 --- /dev/null +++ b/java/res/xml-fr/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="fr"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_azerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_azerty_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_azerty_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-hr/kbd_qwerty.xml b/java/res/xml-hr/kbd_qwerty.xml deleted file mode 100644 index ca92e86a7..000000000 --- a/java/res/xml-hr/kbd_qwerty.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="hr" -> - <!-- TODO: Dedicated Croatian layout especially for tablet. --> - <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> -</Keyboard> diff --git a/java/res/xml-hr/keyboard_set.xml b/java/res/xml-hr/keyboard_set.xml new file mode 100644 index 000000000..e17aefdf6 --- /dev/null +++ b/java/res/xml-hr/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="hr"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-hu/keyboard_set.xml b/java/res/xml-hu/keyboard_set.xml new file mode 100644 index 000000000..0f6e5759e --- /dev/null +++ b/java/res/xml-hu/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="hu"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-iw/kbd_qwerty.xml b/java/res/xml-iw/kbd_qwerty.xml deleted file mode 100644 index 54cd4b5e9..000000000 --- a/java/res/xml-iw/kbd_qwerty.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="iw" - latin:isRtlKeyboard="true" -> - <include - latin:keyboardLayout="@xml/kbd_rows_hebrew" /> -</Keyboard> diff --git a/java/res/xml-iw/kbd_symbols.xml b/java/res/xml-iw/kbd_symbols.xml deleted file mode 100644 index 9e5c255d0..000000000 --- a/java/res/xml-iw/kbd_symbols.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:isRtlKeyboard="true" -> - <include - latin:keyboardLayout="@xml/kbd_rows_symbols" /> -</Keyboard> diff --git a/java/res/xml-iw/kbd_symbols_shift.xml b/java/res/xml-iw/kbd_symbols_shift.xml deleted file mode 100644 index 934e6f849..000000000 --- a/java/res/xml-iw/kbd_symbols_shift.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:isRtlKeyboard="true" -> - <include - latin:keyboardLayout="@xml/kbd_rows_symbols_shift" /> -</Keyboard> diff --git a/java/res/xml-iw/keyboard_set.xml b/java/res/xml-iw/keyboard_set.xml new file mode 100644 index 000000000..501ba96ee --- /dev/null +++ b/java/res/xml-iw/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="iw"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_hebrew" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-ka/keyboard_set.xml b/java/res/xml-ka/keyboard_set.xml new file mode 100644 index 000000000..1b0bc2df6 --- /dev/null +++ b/java/res/xml-ka/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="ka"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_georgian" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-ky/keyboard_set.xml b/java/res/xml-ky/keyboard_set.xml new file mode 100644 index 000000000..71215c5e4 --- /dev/null +++ b/java/res/xml-ky/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="ky"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-land/kbd_number.xml b/java/res/xml-land/kbd_number.xml index f5930ef41..7cc0fb274 100644 --- a/java/res/xml-land/kbd_number.xml +++ b/java/res/xml-land/kbd_number.xml @@ -24,5 +24,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_number" /> + latin:keyboardLayout="@xml/rows_number" /> </Keyboard> diff --git a/java/res/xml-land/kbd_phone.xml b/java/res/xml-land/kbd_phone.xml index 3b1fb36ff..aa54b8390 100644 --- a/java/res/xml-land/kbd_phone.xml +++ b/java/res/xml-land/kbd_phone.xml @@ -24,5 +24,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_phone" /> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-land/kbd_phone_shift.xml b/java/res/xml-land/kbd_phone_symbols.xml index e59664776..41ba6cf3b 100644 --- a/java/res/xml-land/kbd_phone_shift.xml +++ b/java/res/xml-land/kbd_phone_symbols.xml @@ -24,5 +24,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_phone_shift" /> + latin:keyboardLayout="@xml/rows_phone_symbols" /> </Keyboard> diff --git a/java/res/xml-mk/keyboard_set.xml b/java/res/xml-mk/keyboard_set.xml new file mode 100644 index 000000000..5eabe8c6b --- /dev/null +++ b/java/res/xml-mk/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="mk"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_south_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-nb/kbd_qwerty.xml b/java/res/xml-nb/kbd_qwerty.xml deleted file mode 100644 index 1f4e86e89..000000000 --- a/java/res/xml-nb/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="nb" -> - <include - latin:keyboardLayout="@xml/kbd_rows_scandinavian" /> -</Keyboard> diff --git a/java/res/xml-nb/keyboard_set.xml b/java/res/xml-nb/keyboard_set.xml new file mode 100644 index 000000000..2d585a908 --- /dev/null +++ b/java/res/xml-nb/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="nb"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-pl/keyboard_set.xml b/java/res/xml-pl/keyboard_set.xml new file mode 100644 index 000000000..6d2737929 --- /dev/null +++ b/java/res/xml-pl/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="pl"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-pt/kbd_qwerty.xml b/java/res/xml-pt/kbd_qwerty.xml deleted file mode 100644 index f5dcbc61b..000000000 --- a/java/res/xml-pt/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="pt" -> - <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> -</Keyboard> diff --git a/java/res/xml-pt/keyboard_set.xml b/java/res/xml-pt/keyboard_set.xml new file mode 100644 index 000000000..65f9634ce --- /dev/null +++ b/java/res/xml-pt/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="pt"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-ro/keyboard_set.xml b/java/res/xml-ro/keyboard_set.xml new file mode 100644 index 000000000..6c34966d0 --- /dev/null +++ b/java/res/xml-ro/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="ro"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-ru/kbd_qwerty.xml b/java/res/xml-ru/kbd_qwerty.xml deleted file mode 100644 index aee1b1bfc..000000000 --- a/java/res/xml-ru/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2008, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="ru" -> - <include - latin:keyboardLayout="@xml/kbd_rows_russian" /> -</Keyboard> diff --git a/java/res/xml-ru/keyboard_set.xml b/java/res/xml-ru/keyboard_set.xml new file mode 100644 index 000000000..76daf32a7 --- /dev/null +++ b/java/res/xml-ru/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="ru"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sk/keyboard_set.xml b/java/res/xml-sk/keyboard_set.xml new file mode 100644 index 000000000..b283d968a --- /dev/null +++ b/java/res/xml-sk/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="sk"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sl/keyboard_set.xml b/java/res/xml-sl/keyboard_set.xml new file mode 100644 index 000000000..dbb2782f0 --- /dev/null +++ b/java/res/xml-sl/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="sl"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sr/kbd_qwerty.xml b/java/res/xml-sr/kbd_qwerty.xml deleted file mode 100644 index 58fc187c2..000000000 --- a/java/res/xml-sr/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2008, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="sr" -> - <include - latin:keyboardLayout="@xml/kbd_rows_serbian" /> -</Keyboard> diff --git a/java/res/xml-sr/keyboard_set.xml b/java/res/xml-sr/keyboard_set.xml new file mode 100644 index 000000000..71dedf497 --- /dev/null +++ b/java/res/xml-sr/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="sr"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_south_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sv/kbd_qwerty.xml b/java/res/xml-sv/kbd_qwerty.xml deleted file mode 100644 index e29d9abce..000000000 --- a/java/res/xml-sv/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2008, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="sv" -> - <include - latin:keyboardLayout="@xml/kbd_rows_scandinavian" /> -</Keyboard> diff --git a/java/res/xml-sv/keyboard_set.xml b/java/res/xml-sv/keyboard_set.xml new file mode 100644 index 000000000..7135fc54b --- /dev/null +++ b/java/res/xml-sv/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="sv"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sw600dp-land/kbd_mini_keyboard_template.xml b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml index 8272e02f0..4d8b446a2 100644 --- a/java/res/xml-sw600dp-land/kbd_mini_keyboard_template.xml +++ b/java/res/xml-sw600dp-land/kbd_more_keys_keyboard_template.xml @@ -21,6 +21,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="5%p" latin:rowHeight="@dimen/popup_key_height" - style="?attr/miniKeyboardStyle" + style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-ar/kbd_symbols.xml b/java/res/xml-sw600dp-land/kbd_number.xml index 9e5c255d0..9d358b678 100644 --- a/java/res/xml-ar/kbd_symbols.xml +++ b/java/res/xml-sw600dp-land/kbd_number.xml @@ -20,8 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:isRtlKeyboard="true" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="15.00%p" > <include - latin:keyboardLayout="@xml/kbd_rows_symbols" /> + latin:keyboardLayout="@xml/rows_number" /> </Keyboard> diff --git a/java/res/xml-ar/kbd_qwerty.xml b/java/res/xml-sw600dp-land/kbd_phone.xml index b26a938cc..abac6bd4f 100644 --- a/java/res/xml-ar/kbd_qwerty.xml +++ b/java/res/xml-sw600dp-land/kbd_phone.xml @@ -20,9 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="ar" - latin:isRtlKeyboard="true" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="15.00%p" > <include - latin:keyboardLayout="@xml/kbd_rows_arabic" /> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-sw600dp-land/kbd_phone_symbols.xml b/java/res/xml-sw600dp-land/kbd_phone_symbols.xml new file mode 100644 index 000000000..e3f56bce7 --- /dev/null +++ b/java/res/xml-sw600dp-land/kbd_phone_symbols.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="15.00%p" +> + <!-- Tablet doesn't have phone symbols keyboard --> + <include + latin:keyboardLayout="@xml/rows_phone" /> +</Keyboard> diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_azerty_symbols.xml index 8c730a24f..66254dea0 100644 --- a/java/res/xml-fr/kbd_qwerty.xml +++ b/java/res/xml-sw600dp/kbd_azerty_symbols.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2008, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="fr" > <include - latin:keyboardLayout="@xml/kbd_rows_azerty" /> + latin:keyboardLayout="@xml/rows_10_10_7_symbols" /> </Keyboard> diff --git a/java/res/xml-de/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_azerty_symbols_shift.xml index 89e10b26d..3c5ed5e09 100644 --- a/java/res/xml-de/kbd_qwerty.xml +++ b/java/res/xml-sw600dp/kbd_azerty_symbols_shift.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2008, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="de" > <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> + latin:keyboardLayout="@xml/rows_10_10_7_symbols_shift" /> </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml deleted file mode 100644 index 25fa8b265..000000000 --- a/java/res/xml-sw600dp/kbd_key_styles.xml +++ /dev/null @@ -1,114 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <!-- Base key style for the key which may have settings key as popup key --> - <switch> - <case - latin:clobberSettingsKey="true" - > - <key-style - latin:styleName="f2PopupStyle" - latin:backgroundType="functional" /> - </case> - <default> - <key-style - latin:styleName="f2PopupStyle" - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="\@icon/3|\@integer/key_settings" - latin:backgroundType="functional" /> - </default> - </switch> - <!-- Functional key styles --> - <key-style - latin:styleName="shiftKeyStyle" - latin:code="@integer/key_shift" - latin:keyIcon="iconShiftKey" - latin:keyIconShifted="iconShiftedShiftKey" - latin:backgroundType="sticky" /> - <key-style - latin:styleName="deleteKeyStyle" - latin:code="@integer/key_delete" - latin:keyIcon="iconDeleteKey" - latin:backgroundType="functional" - latin:isRepeatable="true" /> - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyIcon="iconReturnKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="spaceKeyStyle" - latin:code="@integer/key_space" /> - <key-style - latin:styleName="nonSpecialBackgroundSpaceKeyStyle" - latin:code="@integer/key_space" /> - <key-style - latin:styleName="smileyKeyStyle" - latin:keyLabel=":-)" - latin:keyOutputText=":-) " - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_smiley" - latin:maxMoreKeysColumn="5" /> - <key-style - latin:styleName="shortcutKeyStyle" - latin:code="@integer/key_shortcut" - latin:keyIcon="iconShortcutKey" - latin:parentStyle="f2PopupStyle" /> - <key-style - latin:styleName="settingsKeyStyle" - latin:code="@integer/key_settings" - latin:keyIcon="iconSettingsKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="tabKeyStyle" - latin:code="@integer/key_tab" - latin:keyIcon="iconTabKey" - latin:keyIconPreview="iconPreviewTabKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toSymbolKeyStyle" - latin:code="@integer/key_switch_alpha_symbol" - latin:keyLabel="@string/label_to_symbol_key" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toAlphaKeyStyle" - latin:code="@integer/key_switch_alpha_symbol" - latin:keyLabel="@string/label_to_alpha_key" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toMoreSymbolKeyStyle" - latin:code="@integer/key_shift" - latin:keyLabel="@string/label_to_more_symbol_for_tablet_key" - latin:backgroundType="functional" /> - <key-style - latin:styleName="backFromMoreSymbolKeyStyle" - latin:code="@integer/key_shift" - latin:keyLabel="@string/label_to_symbol_key" - latin:backgroundType="functional" /> - <key-style - latin:styleName="comKeyStyle" - latin:keyLabel="@string/keylabel_for_popular_domain" - latin:keyLabelOption="fontNormal|hasPopupHint" - latin:keyOutputText="@string/keylabel_for_popular_domain" - latin:moreKeys="@string/more_keys_for_popular_domain" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_mini_keyboard_template.xml b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml index 0d5795f6a..d90a5884e 100644 --- a/java/res/xml-sw600dp/kbd_mini_keyboard_template.xml +++ b/java/res/xml-sw600dp/kbd_more_keys_keyboard_template.xml @@ -21,6 +21,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="8%p" latin:rowHeight="@dimen/popup_key_height" - style="?attr/miniKeyboardStyle" + style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_number.xml b/java/res/xml-sw600dp/kbd_number.xml index 46114dedf..70cf6a2ca 100644 --- a/java/res/xml-sw600dp/kbd_number.xml +++ b/java/res/xml-sw600dp/kbd_number.xml @@ -20,190 +20,8 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="16.75%p" + latin:keyWidth="15.00%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> - <switch> - <case - latin:passwordInput="true" - > - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="24.875%p" /> - <Key - latin:keyStyle="num1KeyStyle" /> - <Key - latin:keyStyle="num2KeyStyle" /> - <Key - latin:keyStyle="num3KeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="24.875%p" /> - <Key - latin:keyStyle="num4KeyStyle" /> - <Key - latin:keyStyle="num5KeyStyle" /> - <Key - latin:keyStyle="num6KeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="24.875%p" /> - <Key - latin:keyStyle="num7KeyStyle" /> - <Key - latin:keyStyle="num8KeyStyle" /> - <Key - latin:keyStyle="num9KeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyWidth="11.00%p" /> - <Spacer - latin:keyXPos="24.875%p" /> - <Key - latin:keyStyle="num0KeyStyle" /> - <Spacer - latin:keyXPos="-11.00%p" - latin:keyWidth="0%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> - </Row> - </case> - <!-- latin:passwordInput="false" --> - <default> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="11.00%p" /> - <Key - latin:keyLabel="-" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="+" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="." - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="1" - latin:keyStyle="numKeyStyle" - latin:keyXPos="38.75%p" /> - <Key - latin:keyLabel="2" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="3" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="11.00%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="/" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="," - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="4" - latin:keyStyle="numKeyStyle" - latin:keyXPos="38.75%p" /> - <Key - latin:keyLabel="5" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="6" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="11.00%p" /> - <Key - latin:keyLabel="(" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel=")" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="=" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="7" - latin:keyStyle="numKeyStyle" - latin:keyXPos="38.75%p" /> - <Key - latin:keyLabel="8" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="9" - latin:keyStyle="numKeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyWidth="11.00%p" /> - <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" - latin:keyWidth="27.75%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyXPos="38.75%p" /> - <Key - latin:keyLabel="0" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="#" - latin:keyStyle="numKeyStyle" /> - <Spacer - latin:keyXPos="-11.00%p" - latin:keyWidth="0%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> - </Row> - </default> - </switch> + latin:keyboardLayout="@xml/rows_number" /> </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_phone.xml b/java/res/xml-sw600dp/kbd_phone.xml index 303f8145b..72acef21c 100644 --- a/java/res/xml-sw600dp/kbd_phone.xml +++ b/java/res/xml-sw600dp/kbd_phone.xml @@ -20,104 +20,8 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="16.75%p" + latin:keyWidth="15.00%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="15.625%p" /> - <Key - latin:keyLabel="-" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="+" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyStyle="num1KeyStyle" - latin:keyXPos="38.867%p" /> - <Key - latin:keyStyle="num2KeyStyle" /> - <Key - latin:keyStyle="num3KeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="15.625%p" /> - <Key - latin:keyLabel="," - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel="." - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyStyle="num4KeyStyle" - latin:keyXPos="38.867%p" /> - <Key - latin:keyStyle="num5KeyStyle" /> - <Key - latin:keyStyle="num6KeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row> - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyWidth="11.0%p" /> - <Key - latin:keyLabel="(" - latin:keyStyle="numKeyStyle" - latin:keyXPos="15.625%p" - latin:keyWidth="9.25%p" /> - <Key - latin:keyLabel=")" - latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> - <Key - latin:keyStyle="num7KeyStyle" - latin:keyXPos="38.867%p" /> - <Key - latin:keyStyle="num8KeyStyle" /> - <Key - latin:keyStyle="num9KeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyWidth="11.00%p" /> - <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" - latin:keyXPos="15.625%p" - latin:keyWidth="18.50%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyXPos="38.867%p" /> - <Key - latin:keyStyle="num0KeyStyle" /> - <Key - latin:keyLabel="#" - latin:keyStyle="numKeyStyle" /> - <Spacer - latin:keyXPos="-11.00%p" - latin:keyWidth="0%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> - </Row> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_phone_symbols.xml b/java/res/xml-sw600dp/kbd_phone_symbols.xml new file mode 100644 index 000000000..9faeaf4e0 --- /dev/null +++ b/java/res/xml-sw600dp/kbd_phone_symbols.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyWidth="15.00%p" +> + <!-- Tablet doesn't have phone symbols keyboard --> + <include + latin:keyboardLayout="@xml/rows_phone" /> +</Keyboard> diff --git a/java/res/xml-sw600dp/kbd_qwerty_f2.xml b/java/res/xml-sw600dp/kbd_qwerty_f2.xml deleted file mode 100644 index b25afc12f..000000000 --- a/java/res/xml-sw600dp/kbd_qwerty_f2.xml +++ /dev/null @@ -1,73 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <switch> - <case - latin:f2KeyMode="settings" - > - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="fillBoth" /> - </case> - <case - latin:f2KeyMode="shortcutIme" - > - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyWidth="fillBoth" /> - </case> - <!-- shortcutKeyEnabled="false" --> - <default> - <Spacer /> - </default> - </switch> - </case> - <case - latin:f2KeyMode="shortcutImeOrSettings" - > - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyWidth="fillBoth" /> - </case> - <!-- shortcutKeyEnabled="false" --> - <default> - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="fillBoth" /> - </default> - </switch> - </case> - <!-- f2KeyMode="none" --> - <default> - <Spacer /> - </default> - </switch> -</merge> diff --git a/java/res/xml-sw600dp/kbd_qwerty_row1.xml b/java/res/xml-sw600dp/kbd_qwerty_row1.xml deleted file mode 100644 index 07d8e2296..000000000 --- a/java/res/xml-sw600dp/kbd_qwerty_row1.xml +++ /dev/null @@ -1,62 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_arabic.xml b/java/res/xml-sw600dp/kbd_rows_arabic.xml deleted file mode 100644 index c2d3cd4cc..000000000 --- a/java/res/xml-sw600dp/kbd_rows_arabic.xml +++ /dev/null @@ -1,217 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.0%p" - > - <!-- \u0636: ARABIC LETTER DAD --> - <Key - latin:keyLabel="ض" /> - <!-- \u0635: ARABIC LETTER SAD --> - <Key - latin:keyLabel="ص" /> - <!-- \u062b: ARABIC LETTER THEH --> - <Key - latin:keyLabel="ث" /> - <!-- \u0642: ARABIC LETTER QAF - \u06a8: ARABIC LETTER QAF WITH THREE DOTS ABOVE --> - <Key - latin:keyLabel="ق" - latin:moreKeys="ڨ" /> - <!-- \u0641: ARABIC LETTER FEH - \u06a4: ARABIC LETTER VEH - \u06a2: ARABIC LETTER FEH WITH DOT MOVED BELOW - \u06a5: ARABIC LETTER FEH WITH THREE DOTS BELOW --> - <Key - latin:keyLabel="ف" - latin:moreKeys="\u06a4,\u06a2,\u06a5" /> - <!-- \u063a: ARABIC LETTER GHAIN --> - <Key - latin:keyLabel="غ" /> - <!-- \u0639: ARABIC LETTER AIN --> - <Key - latin:keyLabel="ع" /> - <!-- \u0647: ARABIC LETTER HEH - \ufeeb: ARABIC LETTER HEH INITIAL FORM - \u0647\u0640: ARABIC LETTER HEH + Zero width joiner --> - <Key - latin:keyLabel="ه" - latin:moreKeys="\ufeeb|\u0647\u200D" /> - <!-- \u062e: ARABIC LETTER KHAH --> - <Key - latin:keyLabel="خ" /> - <!-- \u062d: ARABIC LETTER HAH --> - <Key - latin:keyLabel="ح" /> - <!-- \u062c: ARABIC LETTER JEEM - \u0686: ARABIC LETTER TCHEH --> - <Key - latin:keyLabel="ج" - latin:moreKeys="چ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.0%p" - > - <!-- \u0634: ARABIC LETTER SHEEN - \u069c: ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> - <Key - latin:keyLabel="ش" - latin:moreKeys="ڜ" - latin:keyXPos="3.0%p" /> - <!-- \u0633: ARABIC LETTER SEEN --> - <Key - latin:keyLabel="س" /> - <!-- \u064a: ARABIC LETTER YEH - \u0626: ARABIC LETTER YEH WITH HAMZA ABOVE - \u0649: ARABIC LETTER ALEF MAKSURA --> - <Key - latin:keyLabel="ي" - latin:moreKeys="\u0626,\u0649" /> - <!-- \u0628: ARABIC LETTER BEH - \u067e: ARABIC LETTER PEH --> - <Key - latin:keyLabel="ب" - latin:moreKeys="پ" /> - <!-- \u0644: ARABIC LETTER LAM - \ufefb: ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM - \u0627: ARABIC LETTER ALEF - \ufef7: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \ufef9: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \ufef5: ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ل" - latin:moreKeys="\ufefb|\u0644\u0627,\ufef7|\u0644\u0623,\ufef9|\u0644\u0625,\ufef5|\u0644\u0622" /> - <!-- \u0627: ARABIC LETTER ALEF - \u0621: ARABIC LETTER HAMZA - \u0671: ARABIC LETTER ALEF WASLA - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ا" - latin:moreKeys="\u0621,\u0671,\u0623,\u0625,\u0622" /> - <!-- \u062a: ARABIC LETTER TEH --> - <Key - latin:keyLabel="ت" /> - <!-- \u0646: ARABIC LETTER NOON --> - <Key - latin:keyLabel="ن" /> - <!-- \u0645: ARABIC LETTER MEEM --> - <Key - latin:keyLabel="م" /> - <!-- \u0643: ARABIC LETTER KAF - \u06af: ARABIC LETTER GAF - \u06a9: ARABIC LETTER KEHEH --> - <Key - latin:keyLabel="ك" - latin:moreKeys="\u06af,\u06a9" /> - <!-- \u0637: ARABIC LETTER TAH --> - <Key - latin:keyLabel="ط" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.0%p" - > - <!-- kbd_row3_smiley --> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="\@" /> - </case> - <case - latin:mode="url" - > - <Key - latin:keyLabel="-" - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="_" - latin:moreKeys="_" /> - </case> - <case - latin:imeAction="actionSearch" - > - <Key - latin:keyLabel=":" - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="+" - latin:moreKeys="+" /> - </case> - <default> - <Key - latin:keyStyle="smileyKeyStyle" /> - </default> - </switch> - <!-- \u0626: ARABIC LETTER YEH WITH HAMZA ABOVE --> - <Key - latin:keyLabel="ئ" /> - <!-- \u0621: ARABIC LETTER HAMZA --> - <Key - latin:keyLabel="ء" /> - <!-- \u0624: ARABIC LETTER WAW WITH HAMZA ABOVE --> - <Key - latin:keyLabel="ؤ" /> - <!-- \u0631: ARABIC LETTER REH --> - <Key - latin:keyLabel="ر" /> - <!-- \u0630: ARABIC LETTER THAL --> - <Key - latin:keyLabel="ذ" /> - <!-- \u0649: ARABIC LETTER ALEF MAKSURA --> - <Key - latin:keyLabel="ى" /> - <!-- \u0629: ARABIC LETTER TEH MARBUTA --> - <Key - latin:keyLabel="ة" /> - <!-- \u0648: ARABIC LETTER WAW --> - <Key - latin:keyLabel="و" /> - <!-- \u0632: ARABIC LETTER ZAIN - \u0698: ARABIC LETTER JEH --> - <Key - latin:keyLabel="ز" - latin:moreKeys="ژ" /> - <!-- \u0638: ARABIC LETTER ZAH --> - <Key - latin:keyLabel="ظ" /> - <!-- \u062f: ARABIC LETTER DAL --> - <Key - latin:keyLabel="د" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_azerty.xml b/java/res/xml-sw600dp/kbd_rows_azerty.xml deleted file mode 100644 index 8ae74557c..000000000 --- a/java/res/xml-sw600dp/kbd_rows_azerty.xml +++ /dev/null @@ -1,150 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" - latin:keyXPos="5.0%p" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="m" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="10.0%p" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="\'" /> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> - </case> - <default> - <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> - </default> - </switch> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_hebrew.xml b/java/res/xml-sw600dp/kbd_rows_hebrew.xml deleted file mode 100644 index a8adbd34c..000000000 --- a/java/res/xml-sw600dp/kbd_rows_hebrew.xml +++ /dev/null @@ -1,147 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="9.0%p" - > - <include - latin:keyboardLayout="@xml/kbd_row4_apostrophe_dash" /> - <Key - latin:keyLabel="ק" /> - <Key - latin:keyLabel="ר" /> - <Key - latin:keyLabel="א" /> - <Key - latin:keyLabel="ט" /> - <Key - latin:keyLabel="ו" /> - <Key - latin:keyLabel="ן" /> - <Key - latin:keyLabel="ם" /> - <Key - latin:keyLabel="פ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-12.000%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="ש" - latin:keyXPos="4.500%p" /> - <Key - latin:keyLabel="ד" /> - <Key - latin:keyLabel="ג" - latin:moreKeys="ג׳" /> - <Key - latin:keyLabel="כ" /> - <Key - latin:keyLabel="ע" /> - <Key - latin:keyLabel="י" - latin:moreKeys="ײַ" /> - <Key - latin:keyLabel="ח" - latin:moreKeys="ח׳" /> - <Key - latin:keyLabel="ל" /> - <Key - latin:keyLabel="ך" /> - <Key - latin:keyLabel="ף" /> - </Row> - <Row - latin:keyWidth="8.9%p" - > - <!-- kbd_row3_smiley --> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="\@" - latin:keyWidth="10.0%p" /> - </case> - <case - latin:mode="url" - > - <Key - latin:keyLabel="-" - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="_" - latin:moreKeys="_" - latin:keyWidth="10.0%p" /> - </case> - <case - latin:imeAction="actionSearch" - > - <Key - latin:keyLabel=":" - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="+" - latin:moreKeys="+" - latin:keyWidth="10.0%p" /> - </case> - <default> - <Key - latin:keyStyle="smileyKeyStyle" - latin:keyWidth="10.0%p" /> - </default> - </switch> - <Key - latin:keyLabel="ז" - latin:moreKeys="ז׳" /> - <Key - latin:keyLabel="ס" /> - <Key - latin:keyLabel="ב" /> - <Key - latin:keyLabel="ה" /> - <Key - latin:keyLabel="נ" /> - <Key - latin:keyLabel="מ" /> - <Key - latin:keyLabel="צ" - latin:moreKeys="צ׳" /> - <Key - latin:keyLabel="ת" - latin:moreKeys="ת׳" /> - <Key - latin:keyLabel="ץ" - latin:moreKeys="ץ׳" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-10.400%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_qwertz.xml b/java/res/xml-sw600dp/kbd_rows_qwertz.xml deleted file mode 100644 index 98667e09c..000000000 --- a/java/res/xml-sw600dp/kbd_rows_qwertz.xml +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <Row - latin:keyWidth="8.9%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="10.0%p" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> - </case> - <default> - <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> - </default> - </switch> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_russian.xml b/java/res/xml-sw600dp/kbd_rows_russian.xml deleted file mode 100644 index cc9ad3aa7..000000000 --- a/java/res/xml-sw600dp/kbd_rows_russian.xml +++ /dev/null @@ -1,140 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.60%p" - > - <Key - latin:keyLabel="й" /> - <Key - latin:keyLabel="ц" /> - <Key - latin:keyLabel="у" /> - <Key - latin:keyLabel="к" /> - <Key - latin:keyLabel="е" - latin:moreKeys="@string/more_keys_for_cyrillic_e" /> - <Key - latin:keyLabel="н" /> - <Key - latin:keyLabel="г" /> - <Key - latin:keyLabel="ш" /> - <Key - latin:keyLabel="щ" /> - <Key - latin:keyLabel="з" /> - <Key - latin:keyLabel="х" /> - <Key - latin:keyLabel="ъ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.60%p" - > - <Key - latin:keyLabel="ф" - latin:keyXPos="2.25%p" /> - <Key - latin:keyLabel="ы" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="п" /> - <Key - latin:keyLabel="р" /> - <Key - latin:keyLabel="о" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ж" /> - <Key - latin:keyLabel="э" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.60%p" - > - <Key - latin:keyStyle="shiftKeyStyle" /> - <Key - latin:keyLabel="я" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="м" /> - <Key - latin:keyLabel="и" /> - <Key - latin:keyLabel="т" /> - <Key - latin:keyLabel="ь" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="ю" /> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> - </case> - <default> - <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> - </default> - </switch> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_scandinavian.xml b/java/res/xml-sw600dp/kbd_rows_scandinavian.xml deleted file mode 100644 index 19fb5212b..000000000 --- a/java/res/xml-sw600dp/kbd_rows_scandinavian.xml +++ /dev/null @@ -1,140 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.9%p" - > - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyLabel="å" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.9%p" - > - <Key - latin:keyLabel="a" - latin:keyXPos="3.5%p" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_10" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_10" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.9%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="10.0%p" /> - <Spacer - latin:keyWidth="4.35%p" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> - <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <Spacer - latin:keyWidth="4.35%p" /> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_serbian.xml b/java/res/xml-sw600dp/kbd_rows_serbian.xml deleted file mode 100644 index db7560cdc..000000000 --- a/java/res/xml-sw600dp/kbd_rows_serbian.xml +++ /dev/null @@ -1,118 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.0%p" - > - <Key - latin:keyLabel="љ" - latin:keyXPos="2.15%p" /> - <Key - latin:keyLabel="њ" /> - <Key - latin:keyLabel="е" /> - <Key - latin:keyLabel="р" /> - <Key - latin:keyLabel="т" /> - <Key - latin:keyLabel="з" /> - <Key - latin:keyLabel="у" /> - <Key - latin:keyLabel="и" /> - <Key - latin:keyLabel="о" /> - <Key - latin:keyLabel="п" /> - <Key - latin:keyLabel="ш" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.9%p" - > - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ф" /> - <Key - latin:keyLabel="г" /> - <Key - latin:keyLabel="х" /> - <Key - latin:keyLabel="ј" /> - <Key - latin:keyLabel="к" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="ћ" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.5%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="8.0%p" /> - <Key - latin:keyLabel="ѕ" /> - <Key - latin:keyLabel="џ" /> - <Key - latin:keyLabel="ц" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="н" /> - <Key - latin:keyLabel="м" /> - <Key - latin:keyLabel="ђ" /> - <Key - latin:keyLabel="ж" /> - <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_spanish.xml b/java/res/xml-sw600dp/kbd_rows_spanish.xml deleted file mode 100644 index 8506af697..000000000 --- a/java/res/xml-sw600dp/kbd_rows_spanish.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" - latin:keyXPos="5.0%p" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="ñ" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_symbols.xml b/java/res/xml-sw600dp/kbd_rows_symbols.xml deleted file mode 100644 index bb48fe734..000000000 --- a/java/res/xml-sw600dp/kbd_rows_symbols.xml +++ /dev/null @@ -1,172 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="@string/keylabel_for_symbols_1" - latin:moreKeys="@string/more_keys_for_symbols_1" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_2" - latin:moreKeys="@string/more_keys_for_symbols_2" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_3" - latin:moreKeys="@string/more_keys_for_symbols_3" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_4" - latin:moreKeys="@string/more_keys_for_symbols_4" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_5" - latin:moreKeys="@string/more_keys_for_symbols_5" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_6" - latin:moreKeys="@string/more_keys_for_symbols_6" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_7" - latin:moreKeys="@string/more_keys_for_symbols_7" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_8" - latin:moreKeys="@string/more_keys_for_symbols_8" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_9" - latin:moreKeys="@string/more_keys_for_symbols_9" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_0" - latin:moreKeys="@string/more_keys_for_symbols_0" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="#" - latin:keyXPos="4.5%p" /> - <Key - latin:keyStyle="currencyKeyStyle" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_percent" - latin:moreKeys="@string/more_keys_for_symbols_percent" /> - <Key - latin:keyLabel="&" /> - <Key - latin:keyLabel="*" - latin:moreKeys="@string/more_keys_for_star" /> - <Key - latin:keyLabel="-" - latin:moreKeys="_,–,—" /> - <Key - latin:keyLabel="+" - latin:moreKeys="@string/more_keys_for_plus" /> - <Key - latin:keyLabel="(" - latin:moreKeys="[,{,<" /> - <Key - latin:keyLabel=")" - latin:moreKeys="],},>" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.9%p" - > - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyWidth="10.0%p" /> - <Key - latin:keyLabel="<" - latin:moreKeys="≤,«,‹" /> - <Key - latin:keyLabel=">" - latin:moreKeys="≥,»,›" /> - <Key - latin:keyLabel="=" - latin:moreKeys="≠,≈" /> - <switch> - <case - latin:mode="url" - > - <Key - latin:keyLabel="\'" - latin:moreKeys="‘,’,‚,‛" /> - </case> - <default> - <Key - latin:keyLabel=":" /> - </default> - </switch> - <Key - latin:keyLabel="@string/keylabel_for_symbols_semicolon" - latin:moreKeys="@string/more_keys_for_symbols_semicolon" /> - <Key - latin:keyLabel="@string/keylabel_for_comma" - latin:moreKeys="@string/more_keys_for_comma" /> - <Key - latin:keyLabel="." /> - <Key - latin:keyLabel="!" - latin:moreKeys="¡" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_question" - latin:moreKeys="@string/more_keys_for_symbols_question" /> - <Key - latin:keyLabel="/" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.9%p" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="13.0%p" /> - <Key - latin:keyStyle="tabKeyStyle" /> - <Key - latin:keyLabel="\@" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="30.750%p" - latin:keyWidth="39.750%p" /> - <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. --> - <!-- latin:moreKeys="“,”,„,‟,«,»,‘,’,‚,‛" --> - <Key - latin:keyLabel=""" - latin:moreKeys="“,”,«,»,‘,’,‚,‛" /> - <Key - latin:keyLabel="_" /> - <Spacer - latin:keyXPos="-10.00%p" - latin:keyWidth="0%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> - </Row> -</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml deleted file mode 100644 index 8e4751502..000000000 --- a/java/res/xml-sw600dp/kbd_rows_symbols_shift.xml +++ /dev/null @@ -1,132 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="~" /> - <Key - latin:keyLabel="`" /> - <Key - latin:keyLabel="|" /> - <Key - latin:keyLabel="•" - latin:moreKeys="@string/more_keys_for_bullet" /> - <Key - latin:keyLabel="√" /> - <Key - latin:keyLabel="π" - latin:moreKeys="Π" /> - <Key - latin:keyLabel="÷" /> - <Key - latin:keyLabel="×" /> - <Key - latin:keyLabel="§" - latin:moreKeys="¶" /> - <Key - latin:keyLabel="Δ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-10.0%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="9.0%p" - > - <Key - latin:keyLabel="£" - latin:keyXPos="4.5%p" /> - <Key - latin:keyStyle="moreCurrency1KeyStyle" /> - <Key - latin:keyStyle="moreCurrency2KeyStyle" /> - <Key - latin:keyStyle="moreCurrency3KeyStyle" /> - <Key - latin:keyLabel="^" - latin:moreKeys="↑,↓,←,→" /> - <Key - latin:keyLabel="°" - latin:moreKeys="′,″" /> - <Key - latin:keyLabel="±" - latin:moreKeys="∞" /> - <Key - latin:keyLabel="{" /> - <Key - latin:keyLabel="}" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.9%p" - > - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyWidth="10.0%p" /> - <Key - latin:keyLabel="\\" /> - <Key - latin:keyLabel="©" /> - <Key - latin:keyLabel="®" /> - <Key - latin:keyLabel="™" /> - <Key - latin:keyLabel="℅" /> - <Key - latin:keyLabel="[" /> - <Key - latin:keyLabel="]" /> - <Key - latin:keyLabel="¡" /> - <Key - latin:keyLabel="¿" /> - </Row> - <Row - latin:keyWidth="8.9%p" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="13.0%p" /> - <Key - latin:keyStyle="tabKeyStyle" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="30.750%p" - latin:keyWidth="39.750%p" /> - <Spacer - latin:keyXPos="-10.00%p" - latin:keyWidth="0%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> - </Row> -</merge> diff --git a/java/res/xml-sw600dp/kbd_spanish_symbols.xml b/java/res/xml-sw600dp/kbd_spanish_symbols.xml new file mode 100644 index 000000000..66254dea0 --- /dev/null +++ b/java/res/xml-sw600dp/kbd_spanish_symbols.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_10_10_7_symbols" /> +</Keyboard> diff --git a/java/res/xml-sw600dp/kbd_spanish_symbols_shift.xml b/java/res/xml-sw600dp/kbd_spanish_symbols_shift.xml new file mode 100644 index 000000000..3c5ed5e09 --- /dev/null +++ b/java/res/xml-sw600dp/kbd_spanish_symbols_shift.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_10_10_7_symbols_shift" /> +</Keyboard> diff --git a/java/res/xml-sw600dp/key_azerty_quote.xml b/java/res/xml-sw600dp/key_azerty_quote.xml new file mode 100644 index 000000000..0e4a8ecdd --- /dev/null +++ b/java/res/xml-sw600dp/key_azerty_quote.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="\'" + latin:keyHintLabel=":" + latin:moreKeys=":" + latin:keyStyle="hasShiftedLetterHintStyle" /> +</merge> diff --git a/java/res/xml-sw600dp/key_greek_semicolon.xml b/java/res/xml-sw600dp/key_greek_semicolon.xml new file mode 100644 index 000000000..3f09419b1 --- /dev/null +++ b/java/res/xml-sw600dp/key_greek_semicolon.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel=";" + latin:keyHintLabel=":" + latin:moreKeys=":" + latin:keyStyle="hasShiftedLetterHintStyle" /> +</merge> diff --git a/java/res/xml-sw600dp/key_shortcut.xml b/java/res/xml-sw600dp/key_shortcut.xml new file mode 100644 index 000000000..8869ab930 --- /dev/null +++ b/java/res/xml-sw600dp/key_shortcut.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:shortcutKeyEnabled="true" + latin:clobberSettingsKey="false" + > + <Key + latin:keyStyle="shortcutKeyStyle" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="@string/settings_as_more_key" + latin:keyWidth="fillBoth" /> + </case> + <case + latin:shortcutKeyEnabled="true" + latin:clobberSettingsKey="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" + latin:keyWidth="fillBoth" /> + </case> + <case + latin:shortcutKeyEnabled="false" + latin:clobberSettingsKey="false" + > + <Key + latin:keyStyle="settingsKeyStyle" + latin:keyWidth="fillBoth" /> + </case> + <!-- shortcutKeyEnabled="false" clobberSettingsKey="true" --> + <default> + <Spacer /> + </default> + </switch> +</merge> diff --git a/java/res/xml-sw600dp/kbd_row3_smiley.xml b/java/res/xml-sw600dp/key_smiley.xml index f9b647cdf..3430d7898 100644 --- a/java/res/xml-sw600dp/kbd_row3_smiley.xml +++ b/java/res/xml-sw600dp/key_smiley.xml @@ -26,37 +26,29 @@ latin:mode="email" > <Key - latin:keyLabel="\@" - latin:keyXPos="-8.9%p" - latin:keyWidth="fillBoth" /> + latin:keyLabel="\@" /> </case> <case latin:mode="url" > <Key latin:keyLabel="-" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="_" latin:moreKeys="_" - latin:keyXPos="-8.9%p" - latin:keyWidth="fillBoth" /> + latin:keyStyle="hasShiftedLetterHintStyle" /> </case> <case latin:imeAction="actionSearch" > <Key latin:keyLabel=":" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="+" latin:moreKeys="+" - latin:keyXPos="-8.9%p" - latin:keyWidth="fillBoth" /> + latin:keyStyle="hasShiftedLetterHintStyle" /> </case> <default> <Key - latin:keyStyle="smileyKeyStyle" - latin:keyXPos="-8.9%p" - latin:keyWidth="fillBoth" /> + latin:keyStyle="smileyKeyStyle" /> </default> </switch> </merge> diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml new file mode 100644 index 000000000..a263acd9b --- /dev/null +++ b/java/res/xml-sw600dp/key_styles_common.xml @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <key-style + latin:styleName="hasShiftedLetterHintStyle" + latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" /> + </case> + <default> + <key-style + latin:styleName="hasShiftedLetterHintStyle" + latin:keyLabelFlags="hasShiftedLetterHint" /> + </default> + </switch> + <!-- Functional key styles --> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted" + > + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> + </case> + <case + latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted" + > + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOn" /> + </case> + <default> + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKey" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> + </default> + </switch> + <key-style + latin:styleName="deleteKeyStyle" + latin:code="@integer/key_delete" + latin:keyIcon="iconDeleteKey" + latin:keyActionFlags="isRepeatable|noKeyPreview" + latin:backgroundType="functional" /> + <include + latin:keyboardLayout="@xml/key_styles_enter" /> + <key-style + latin:styleName="spaceKeyStyle" + latin:code="@integer/key_space" + latin:keyActionFlags="noKeyPreview" /> + <key-style + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" /> + <key-style + latin:styleName="smileyKeyStyle" + latin:keyLabel=":-)" + latin:keyOutputText=":-) " + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/more_keys_for_smiley" /> + <key-style + latin:styleName="shortcutKeyStyle" + latin:code="@integer/key_shortcut" + latin:keyIcon="iconShortcutKey" + latin:keyIconDisabled="iconDisabledShortcutKey" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:backgroundType="functional" /> + <key-style + latin:styleName="settingsKeyStyle" + latin:code="@integer/key_settings" + latin:keyIcon="iconSettingsKey" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:backgroundType="functional" /> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + latin:navigatePrevious="true" + > + <key-style + latin:styleName="tabKeyStyle" + latin:code="@integer/key_action_previous" + latin:keyIcon="iconTabKey" + latin:keyIconPreview="iconPreviewTabKey" + latin:backgroundType="functional" /> + </case> + <default> + <key-style + latin:styleName="tabKeyStyle" + latin:code="@integer/key_tab" + latin:keyIcon="iconTabKey" + latin:keyIconPreview="iconPreviewTabKey" + latin:backgroundType="functional" /> + </default> + </switch> + <key-style + latin:styleName="toSymbolKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" + latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="toAlphaKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" + latin:keyLabel="@string/label_to_alpha_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="toMoreSymbolKeyStyle" + latin:code="@integer/key_shift" + latin:keyLabel="@string/label_to_more_symbol_for_tablet_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="backFromMoreSymbolKeyStyle" + latin:code="@integer/key_shift" + latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="comKeyStyle" + latin:keyLabel="@string/keylabel_for_popular_domain" + latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase" + latin:keyOutputText="@string/keylabel_for_popular_domain" + latin:moreKeys="@string/more_keys_for_popular_domain" /> +</merge> diff --git a/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw600dp/keys_apostrophe_dash.xml index 9536e81da..a53c1e4ab 100644 --- a/java/res/xml-sw600dp/kbd_row4_apostrophe_dash.xml +++ b/java/res/xml-sw600dp/keys_apostrophe_dash.xml @@ -33,16 +33,16 @@ > <Key latin:keyLabel="/" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel=":" - latin:moreKeys=":" /> + latin:moreKeys=":" + latin:keyStyle="hasShiftedLetterHintStyle" /> </case> <default> <Key latin:keyLabel="@string/keylabel_for_apostrophe" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="@string/keyhintlabel_for_apostrophe" - latin:moreKeys="@string/more_keys_for_apostrophe" /> + latin:moreKeys="@string/more_keys_for_apostrophe" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> <switch> @@ -55,9 +55,9 @@ <default> <Key latin:keyLabel="@string/keylabel_for_dash" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="@string/keyhintlabel_for_dash" - latin:moreKeys="@string/more_keys_for_dash" /> + latin:moreKeys="@string/more_keys_for_dash" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> </merge> diff --git a/java/res/xml-sw600dp/kbd_qwerty_row4.xml b/java/res/xml-sw600dp/row_qwerty4.xml index ef0292279..eec35b078 100644 --- a/java/res/xml-sw600dp/kbd_qwerty_row4.xml +++ b/java/res/xml-sw600dp/row_qwerty4.xml @@ -45,32 +45,46 @@ <default> <Key latin:keyLabel="/" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="\@" - latin:moreKeys="\@" /> + latin:moreKeys="\@" + latin:keyStyle="hasShiftedLetterHintStyle" /> + </default> + </switch> + <switch> + <case + latin:languageCode="fa" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="30.850%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="39.750%p" /> </default> </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="30.750%p" - latin:keyWidth="39.750%p" /> <switch> <case latin:languageCode="iw" > <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> + latin:keyboardLayout="@xml/keys_comma_period" /> </case> <!-- not languageCode="iw" --> <default> <include - latin:keyboardLayout="@xml/kbd_row4_apostrophe_dash" /> + latin:keyboardLayout="@xml/keys_apostrophe_dash" /> </default> </switch> <Spacer latin:keyXPos="-10.00%p" latin:keyWidth="0%p" /> <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> + latin:keyboardLayout="@xml/key_shortcut" /> </Row> </merge> diff --git a/java/res/xml-sw600dp/rowkeys_arabic1.xml b/java/res/xml-sw600dp/rowkeys_arabic1.xml new file mode 100644 index 000000000..44fdc676d --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_arabic1.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0636: "ض" ARABIC LETTER DAD --> + <Key + latin:keyLabel="ض" /> + <!-- U+0635: "ص" ARABIC LETTER SAD --> + <Key + latin:keyLabel="ص" /> + <!-- U+062B: "ث" ARABIC LETTER THEH --> + <Key + latin:keyLabel="ث" /> + <!-- U+0642: "ق" ARABIC LETTER QAF + U+06A8: "ڨ" ARABIC LETTER QAF WITH THREE DOTS ABOVE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A8 ARABIC LETTER QAF WITH THREE DOTS ABOVE --> + <Key + latin:keyLabel="ق" + latin:moreKeys="ڨ" /> + <!-- U+0641: "ف" ARABIC LETTER FEH + U+06A4: "ڤ" ARABIC LETTER VEH + U+06A2: "ڢ" ARABIC LETTER FEH WITH DOT MOVED BELOW + U+06A5: "ڥ" ARABIC LETTER FEH WITH THREE DOTS BELOW --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A2 ARABIC LETTER FEH WITH DOT MOVED BELOW --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A5 ARABIC LETTER FEH WITH THREE DOTS BELOW --> + <Key + latin:keyLabel="ف" + latin:moreKeys="ڤ,ڢ,ڥ" /> + <!-- U+063A: "غ" ARABIC LETTER GHAIN --> + <Key + latin:keyLabel="غ" /> + <!-- U+0639: "ع" ARABIC LETTER AIN --> + <Key + latin:keyLabel="ع" /> + <!-- U+0647: "ه" ARABIC LETTER HEH + U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM + U+0647 U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER --> + <Key + latin:keyLabel="ه" + latin:moreKeys="ﻫ|ه‍" /> + <!-- U+062E: "خ" ARABIC LETTER KHAH --> + <Key + latin:keyLabel="خ" /> + <!-- U+062D: "ح" ARABIC LETTER HAH --> + <Key + latin:keyLabel="ح" /> + <!-- U+062C: "ج" ARABIC LETTER JEEM + U+0686: "چ" ARABIC LETTER TCHEH --> + <Key + latin:keyLabel="ج" + latin:moreKeys="چ" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_arabic2.xml b/java/res/xml-sw600dp/rowkeys_arabic2.xml new file mode 100644 index 000000000..3eba2fbf3 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_arabic2.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0634: "ش" ARABIC LETTER SHEEN + U+069C: "ڜ" ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+069C ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> + <Key + latin:keyLabel="ش" + latin:moreKeys="ڜ" /> + <!-- U+0633: "س" ARABIC LETTER SEEN --> + <Key + latin:keyLabel="س" /> + <!-- U+064A: "ي" ARABIC LETTER YEH + U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE + U+0649: "ى" ARABIC LETTER ALEF MAKSURA --> + <Key + latin:keyLabel="ي" + latin:moreKeys="ئ,ى" /> + <!-- U+0628: "ب" ARABIC LETTER BEH + U+067E: "پ" ARABIC LETTER PEH --> + <Key + latin:keyLabel="ب" + latin:moreKeys="پ" /> + <!-- U+0644: "ل" ARABIC LETTER LAM + U+FEFB: "ﻻ" ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + U+0627: "ا" ARABIC LETTER ALEF + U+FEF7: "ﻷ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE + U+FEF9: "ﻹ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM + U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW + U+FEF5: "ﻵ" ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE --> + <Key + latin:keyLabel="ل" + latin:moreKeys="ﻻ|لا,ﻷ|لأ,ﻹ|لإ,ﻵ|لآ" /> + <!-- U+0627: "ا" ARABIC LETTER ALEF + U+0621: "ء" ARABIC LETTER HAMZA + U+0671: "ٱ" ARABIC LETTER ALEF WASLA + U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE + U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE --> + <Key + latin:keyLabel="ا" + latin:moreKeys="ء,ٱ,أ,إ,آ" /> + <!-- U+062A: "ت" ARABIC LETTER TEH --> + <Key + latin:keyLabel="ت" /> + <!-- U+0646: "ن" ARABIC LETTER NOON --> + <Key + latin:keyLabel="ن" /> + <!-- U+0645: "م" ARABIC LETTER MEEM --> + <Key + latin:keyLabel="م" /> + <!-- U+0643: "ك" ARABIC LETTER KAF + U+06AF: "گ" ARABIC LETTER GAF + U+06A9: "ک" ARABIC LETTER KEHEH --> + <Key + latin:keyLabel="ك" + latin:moreKeys="گ,ک" /> + <!-- U+0637: "ط" ARABIC LETTER TAH --> + <Key + latin:keyLabel="ط" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_arabic3.xml b/java/res/xml-sw600dp/rowkeys_arabic3.xml new file mode 100644 index 000000000..911550f4a --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_arabic3.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE --> + <Key + latin:keyLabel="ئ" /> + <!-- U+0621: "ء" ARABIC LETTER HAMZA --> + <Key + latin:keyLabel="ء" /> + <!-- U+0624: "ؤ" ARABIC LETTER WAW WITH HAMZA ABOVE --> + <Key + latin:keyLabel="ؤ" /> + <!-- U+0631: "ر" ARABIC LETTER REH --> + <Key + latin:keyLabel="ر" /> + <!-- U+0630: "ذ" ARABIC LETTER THAL --> + <Key + latin:keyLabel="ذ" /> + <!-- U+0649: "ى" ARABIC LETTER ALEF MAKSURA --> + <Key + latin:keyLabel="ى" /> + <!-- U+0629: "ة" ARABIC LETTER TEH MARBUTA --> + <Key + latin:keyLabel="ة" /> + <!-- U+0648: "و" ARABIC LETTER WAW --> + <Key + latin:keyLabel="و" /> + <!-- U+0632: "ز" ARABIC LETTER ZAIN + U+0698: "ژ" ARABIC LETTER JEH --> + <Key + latin:keyLabel="ز" + latin:moreKeys="ژ" /> + <!-- U+0638: "ظ" ARABIC LETTER ZAH --> + <Key + latin:keyLabel="ظ" /> + <!-- U+062F: "د" ARABIC LETTER DAL --> + <Key + latin:keyLabel="د" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_symbols2.xml b/java/res/xml-sw600dp/rowkeys_symbols2.xml new file mode 100644 index 000000000..e0121a35c --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_symbols2.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="#" /> + <Key + latin:keyStyle="currencyKeyStyle" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_percent" + latin:moreKeys="@string/more_keys_for_symbols_percent" /> + <Key + latin:keyLabel="&" /> + <Key + latin:keyLabel="*" + latin:moreKeys="@string/more_keys_for_star" /> + <!-- U+2013: "–" EN DASH + U+2014: "—" EM DASH --> + <Key + latin:keyLabel="-" + latin:moreKeys="_,–,—" /> + <Key + latin:keyLabel="+" + latin:moreKeys="@string/more_keys_for_plus" /> + <include + latin:keyboardLayout="@xml/keys_parentheses" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_symbols3.xml b/java/res/xml-sw600dp/rowkeys_symbols3.xml new file mode 100644 index 000000000..9293352cf --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_symbols3.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/keys_less_greater" /> + <!-- U+2260: "≠" NOT EQUAL TO + U+2248: "≈" ALMOST EQUAL TO --> + <Key + latin:keyLabel="=" + latin:moreKeys="≠,≈" /> + <switch> + <case + latin:mode="url" + > + <Key + latin:keyLabel="\'" /> + </case> + <default> + <Key + latin:keyLabel=":" /> + </default> + </switch> + <Key + latin:keyLabel="@string/keylabel_for_symbols_semicolon" + latin:moreKeys="@string/more_keys_for_symbols_semicolon" /> + <Key + latin:keyLabel="@string/keylabel_for_comma" + latin:moreKeys="@string/more_keys_for_comma" /> + <Key + latin:keyLabel="." /> + <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK --> + <Key + latin:keyLabel="!" + latin:moreKeys="¡" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_question" + latin:moreKeys="@string/more_keys_for_symbols_question" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml new file mode 100644 index 000000000..356ee2f0e --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_symbols_shift1.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="~" /> + <Key + latin:keyLabel="`" /> + <Key + latin:keyLabel="|" /> + <!-- U+2022: "•" BULLET --> + <Key + latin:keyLabel="•" + latin:moreKeys="@string/more_keys_for_bullet" /> + <!-- U+221A: "√" SQUARE ROOT --> + <Key + latin:keyLabel="√" /> + <!-- U+03C0: "π" GREEK SMALL LETTER PI + U+03A0: "Π" GREEK CAPITAL LETTER PI --> + <Key + latin:keyLabel="π" + latin:moreKeys="Π" /> + <!-- U+00F7: "÷" DIVISION SIGN --> + <Key + latin:keyLabel="÷" /> + <!-- U+00D7: "×" MULTIPLICATION SIGN --> + <Key + latin:keyLabel="×" /> + <!-- U+00A7: "§" SECTION SIGN + U+00B6: "¶" PILCROW SIGN --> + <Key + latin:keyLabel="§" + latin:moreKeys="¶" /> + <!-- U+0394: "Δ" GREEK CAPITAL LETTER DELTA --> + <Key + latin:keyLabel="Δ" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml new file mode 100644 index 000000000..2048b7335 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_symbols_shift2.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyStyle="moreCurrency1KeyStyle" /> + <Key + latin:keyStyle="moreCurrency2KeyStyle" /> + <Key + latin:keyStyle="moreCurrency3KeyStyle" /> + <Key + latin:keyStyle="moreCurrency4KeyStyle" /> + <!-- U+2191: "↑" UPWARDS ARROW + U+2193: "↓" DOWNWARDS ARROW + U+2190: "←" LEFTWARDS ARROW + U+2192: "→" RIGHTWARDS ARROW --> + <Key + latin:keyLabel="^" + latin:moreKeys="↑,↓,←,→" /> + <!-- U+00B0: "°" DEGREE SIGN + U+2032: "′" PRIME + U+2033: "″" DOUBLE PRIME --> + <Key + latin:keyLabel="°" + latin:moreKeys="′,″" /> + <!-- U+00B1: "±" PLUS-MINUS SIGN + U+221E: "∞" INFINITY --> + <Key + latin:keyLabel="±" + latin:moreKeys="∞" /> + <include + latin:keyboardLayout="@xml/keys_curly_brackets" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml b/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml new file mode 100644 index 000000000..8bd865639 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_symbols_shift3.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="\\" /> + <!-- U+00A9: "©" COPYRIGHT SIGN --> + <Key + latin:keyLabel="©" /> + <!-- U+00AE: "®" REGISTERED SIGN --> + <Key + latin:keyLabel="®" /> + <!-- U+2122: "™" TRADE MARK SIGN --> + <Key + latin:keyLabel="™" /> + <!-- U+2105: "℅" CARE OF --> + <Key + latin:keyLabel="℅" /> + <include + latin:keyboardLayout="@xml/keys_square_brackets" /> + <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK --> + <Key + latin:keyLabel="¡" /> + <!-- U+00BF: "¿" INVERTED QUESTION MARK --> + <Key + latin:keyLabel="¿" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml new file mode 100644 index 000000000..bdb1aa0ee --- /dev/null +++ b/java/res/xml-sw600dp/rows_10_10_7_symbols.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols3" /> + <Key + latin:keyLabel="/" + latin:keyXPos="-8.5%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml new file mode 100644 index 000000000..101493423 --- /dev/null +++ b/java/res/xml-sw600dp/rows_10_10_7_symbols_shift.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift3" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols_shift4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_arabic.xml b/java/res/xml-sw600dp/rows_arabic.xml new file mode 100644 index 000000000..55223267f --- /dev/null +++ b/java/res/xml-sw600dp/rows_arabic.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_arabic3" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_azerty.xml b/java/res/xml-sw600dp/rows_azerty.xml new file mode 100644 index 000000000..3ec22d302 --- /dev/null +++ b/java/res/xml-sw600dp/rows_azerty.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_azerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_azerty2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_azerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-8.5%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_bulgarian.xml b/java/res/xml-sw600dp/rows_bulgarian.xml new file mode 100644 index 000000000..a3b77cc12 --- /dev/null +++ b/java/res/xml-sw600dp/rows_bulgarian.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian2" + latin:keyXPos="4.500%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_east_slavic.xml b/java/res/xml-sw600dp/rows_east_slavic.xml new file mode 100644 index 000000000..26fd7dfe1 --- /dev/null +++ b/java/res/xml-sw600dp/rows_east_slavic.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <Key + latin:keyLabel="ъ" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.363%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_georgian.xml b/java/res/xml-sw600dp/rows_georgian.xml new file mode 100644 index 000000000..d4c39af45 --- /dev/null +++ b/java/res/xml-sw600dp/rows_georgian.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_georgian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_georgian2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_georgian3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_greek.xml b/java/res/xml-sw600dp/rows_greek.xml new file mode 100644 index 000000000..8314222c3 --- /dev/null +++ b/java/res/xml-sw600dp/rows_greek.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/key_greek_semicolon" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_greek2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_hebrew.xml b/java/res/xml-sw600dp/rows_hebrew.xml new file mode 100644 index 000000000..a60da3a2b --- /dev/null +++ b/java/res/xml-sw600dp/rows_hebrew.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/keys_apostrophe_dash" /> + <include + latin:keyboardLayout="@xml/rowkeys_hebrew1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew3" + latin:keyXPos="10.0%p" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-8.5%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_nordic.xml b/java/res/xml-sw600dp/rows_nordic.xml new file mode 100644 index 000000000..3a8aa1d33 --- /dev/null +++ b/java/res/xml-sw600dp/rows_nordic.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_nordic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_nordic2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_number_normal.xml b/java/res/xml-sw600dp/rows_number_normal.xml new file mode 100644 index 000000000..be5776b20 --- /dev/null +++ b/java/res/xml-sw600dp/rows_number_normal.xml @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="12.75%p" /> + <Key + latin:keyLabel="-" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <Key + latin:keyLabel="+" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <Key + latin:keyLabel="." + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <Key + latin:keyLabel="1" + latin:keyStyle="numKeyStyle" + latin:keyXPos="42.25%p" /> + <Key + latin:keyLabel="2" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="3" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.00%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="12.75%p" /> + <Key + latin:keyStyle="numStarKeyStyle" + latin:keyWidth="9.25%p" /> + <Key + latin:keyLabel="/" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <switch> + <case + latin:mode="time|datetime" + > + <Key + latin:keyLabel="," + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="@string/more_keys_for_am_pm" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + </case> + <default> + <Key + latin:keyLabel="," + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + </default> + </switch> + <Key + latin:keyLabel="4" + latin:keyStyle="numKeyStyle" + latin:keyXPos="42.25%p" /> + <Key + latin:keyLabel="5" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="6" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-11.00%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="12.75%p" /> + <Key + latin:keyLabel="(" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <Key + latin:keyLabel=")" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + <switch> + <case + latin:mode="time|datetime" + > + <Key + latin:keyLabel=":" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + </case> + <default> + <Key + latin:keyLabel="=" + latin:keyStyle="numKeyStyle" + latin:keyWidth="9.25%p" /> + </default> + </switch> + <Key + latin:keyLabel="7" + latin:keyStyle="numKeyStyle" + latin:keyXPos="42.25%p" /> + <Key + latin:keyLabel="8" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="9" + latin:keyStyle="numKeyStyle" /> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </Row> + <Row> + <Key + latin:keyStyle="numTabKeyStyle" + latin:keyWidth="11.00%p" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="27.75%p" + latin:keyXPos="12.75%p" /> + <Key + latin:keyStyle="numStarKeyStyle" + latin:keyXPos="42.25%p" /> + <Key + latin:keyLabel="0" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="#" + latin:keyStyle="numKeyStyle" /> + <Spacer + latin:keyXPos="-11.00%p" + latin:keyWidth="0%p" /> + <include + latin:keyboardLayout="@xml/key_shortcut" /> + </Row> +</merge> diff --git a/java/res/xml-sw600dp/rows_number_password.xml b/java/res/xml-sw600dp/rows_number_password.xml new file mode 100644 index 000000000..59279fb3b --- /dev/null +++ b/java/res/xml-sw600dp/rows_number_password.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="27.50%p" /> + <Key + latin:keyStyle="num1KeyStyle" /> + <Key + latin:keyStyle="num2KeyStyle" /> + <Key + latin:keyStyle="num3KeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.00%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="27.50%p" /> + <Key + latin:keyStyle="num4KeyStyle" /> + <Key + latin:keyStyle="num5KeyStyle" /> + <Key + latin:keyStyle="num6KeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-11.00%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="27.50%p" /> + <Key + latin:keyStyle="num7KeyStyle" /> + <Key + latin:keyStyle="num8KeyStyle" /> + <Key + latin:keyStyle="num9KeyStyle" /> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </Row> + <Row> + <Key + latin:keyStyle="tabKeyStyle" + latin:keyWidth="11.00%p" /> + <Key + latin:keyStyle="num0KeyStyle" + latin:keyXPos="42.50%p"/> + <Spacer + latin:keyXPos="-11.00%p" + latin:keyWidth="0%p" /> + <include + latin:keyboardLayout="@xml/key_shortcut" /> + </Row> +</merge> diff --git a/java/res/xml-sw600dp/kbd_phone_shift.xml b/java/res/xml-sw600dp/rows_phone.xml index 4c4f8ad12..e8926936f 100644 --- a/java/res/xml-sw600dp/kbd_phone_shift.xml +++ b/java/res/xml-sw600dp/rows_phone.xml @@ -18,18 +18,17 @@ */ --> -<Keyboard +<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="16.75%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> + latin:keyboardLayout="@xml/key_styles_common" /> <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> + latin:keyboardLayout="@xml/key_styles_number" /> <Row> <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> <Spacer - latin:keyWidth="11.00%p" /> + latin:keyWidth="12.75%p" /> <Key latin:keyLabel="-" latin:keyStyle="numKeyStyle" @@ -39,13 +38,11 @@ latin:keyStyle="numKeyStyle" latin:keyWidth="9.25%p" /> <Key - latin:code="44" - latin:keyLabel="@string/label_pause_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" + latin:keyStyle="numPauseKeyStyle" latin:keyWidth="9.25%p" /> <Key latin:keyStyle="num1KeyStyle" - latin:keyXPos="38.867%p" /> + latin:keyXPos="42.25%p" /> <Key latin:keyStyle="num2KeyStyle" /> <Key @@ -53,12 +50,12 @@ <Key latin:keyStyle="deleteKeyStyle" latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> + latin:keyWidth="fillRight" /> </Row> <Row> <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> <Spacer - latin:keyWidth="11.00%p" /> + latin:keyWidth="12.75%p" /> <Key latin:keyLabel="," latin:keyStyle="numKeyStyle" @@ -68,30 +65,29 @@ latin:keyStyle="numKeyStyle" latin:keyWidth="9.25%p" /> <Key - latin:code="59" - latin:keyLabel="@string/label_wait_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" + latin:keyStyle="numWaitKeyStyle" latin:keyWidth="9.25%p" /> <Key latin:keyStyle="num4KeyStyle" - latin:keyXPos="38.867%p" /> + latin:keyXPos="42.25%p" /> <Key latin:keyStyle="num5KeyStyle" /> <Key latin:keyStyle="num6KeyStyle" /> <Key - latin:keyStyle="returnKeyStyle" + latin:keyStyle="enterKeyStyle" latin:keyXPos="-11.00%p" - latin:keyWidth="fillBoth" /> + latin:keyWidth="fillRight" /> </Row> <Row> - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyWidth="11.00%p" /> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="12.75%p" /> <Key latin:keyLabel="(" latin:keyStyle="numKeyStyle" - latin:keyWidth="9.25%p" /> + latin:keyWidth="9.25%p" + latin:keyXPos="12.75%p" /> <Key latin:keyLabel=")" latin:keyStyle="numKeyStyle" @@ -102,7 +98,7 @@ latin:keyWidth="9.25%p" /> <Key latin:keyStyle="num7KeyStyle" - latin:keyXPos="38.867%p" /> + latin:keyXPos="42.25%p" /> <Key latin:keyStyle="num8KeyStyle" /> <Key @@ -113,14 +109,15 @@ </Row> <Row> <Key - latin:keyStyle="tabKeyStyle" + latin:keyStyle="numTabKeyStyle" latin:keyWidth="11.00%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" - latin:keyWidth="27.75%p" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="27.75%p" + latin:keyXPos="12.75%p" /> <Key latin:keyStyle="numStarKeyStyle" - latin:keyXPos="38.867%p" /> + latin:keyXPos="42.25%p" /> <Key latin:keyStyle="num0KeyStyle" /> <Key @@ -130,6 +127,6 @@ latin:keyXPos="-11.00%p" latin:keyWidth="0%p" /> <include - latin:keyboardLayout="@xml/kbd_qwerty_f2" /> + latin:keyboardLayout="@xml/key_shortcut" /> </Row> -</Keyboard> +</merge> diff --git a/java/res/xml-sw600dp/rows_qwerty.xml b/java/res/xml-sw600dp/rows_qwerty.xml new file mode 100644 index 000000000..8e8d5acb6 --- /dev/null +++ b/java/res/xml-sw600dp/rows_qwerty.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_qwertz.xml b/java/res/xml-sw600dp/rows_qwertz.xml new file mode 100644 index 000000000..d8f5bc6c7 --- /dev/null +++ b/java/res/xml-sw600dp/rows_qwertz.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwertz1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwertz3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_south_slavic.xml b/java/res/xml-sw600dp/rows_south_slavic.xml new file mode 100644 index 000000000..8636cbb24 --- /dev/null +++ b/java/res/xml-sw600dp/rows_south_slavic.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.363%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_spanish.xml b/java/res/xml-sw600dp/rows_spanish.xml new file mode 100644 index 000000000..9451e42d7 --- /dev/null +++ b/java/res/xml-sw600dp/rows_spanish.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_spanish2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" + latin:keyXPos="-8.5%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_symbols.xml b/java/res/xml-sw600dp/rows_symbols.xml new file mode 100644 index 000000000..ea9b30245 --- /dev/null +++ b/java/res/xml-sw600dp/rows_symbols.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols2" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols3" /> + <Key + latin:keyLabel="/" + latin:keyXPos="-9.0%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols4" /> +</merge> diff --git a/java/res/xml-sw600dp/rows_symbols4.xml b/java/res/xml-sw600dp/rows_symbols4.xml new file mode 100644 index 000000000..bfc9b2cf6 --- /dev/null +++ b/java/res/xml-sw600dp/rows_symbols4.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="8.9%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyWidth="13.0%p" /> + <Key + latin:keyStyle="tabKeyStyle" /> + <Key + latin:keyLabel="\@" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="39.750%p" /> + <Key + latin:keyLabel=""" + latin:moreKeys="@string/more_keys_for_tablet_double_quote" /> + <Key + latin:keyLabel="_" /> + <Spacer + latin:keyXPos="-10.00%p" + latin:keyWidth="0%p" /> + <include + latin:keyboardLayout="@xml/key_shortcut" /> + </Row> +</merge> diff --git a/java/res/xml-sw600dp/kbd_qwerty_row2.xml b/java/res/xml-sw600dp/rows_symbols_shift.xml index 52a948f20..cc66f9676 100644 --- a/java/res/xml-sw600dp/kbd_qwerty_row2.xml +++ b/java/res/xml-sw600dp/rows_symbols_shift.xml @@ -21,37 +21,38 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> <Row latin:keyWidth="9.0%p" > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift1" /> <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="9.0%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift2" latin:keyXPos="4.5%p" /> <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-14.6%p" + latin:keyStyle="enterKeyStyle" latin:keyWidth="fillBoth" /> </Row> + <Row + latin:keyWidth="9.0%p" + > + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift3" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols_shift4" /> </merge> diff --git a/java/res/xml-sw600dp/rows_symbols_shift4.xml b/java/res/xml-sw600dp/rows_symbols_shift4.xml new file mode 100644 index 000000000..4381bce6d --- /dev/null +++ b/java/res/xml-sw600dp/rows_symbols_shift4.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="8.9%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyWidth="13.0%p" /> + <Key + latin:keyStyle="tabKeyStyle" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="30.750%p" + latin:keyWidth="39.750%p" /> + <Spacer + latin:keyXPos="-10.00%p" + latin:keyWidth="0%p" /> + <include + latin:keyboardLayout="@xml/key_shortcut" /> + </Row> +</merge> diff --git a/java/res/xml-sw768dp-land/kbd_mini_keyboard_template.xml b/java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml index 85e864a6c..f593fa944 100644 --- a/java/res/xml-sw768dp-land/kbd_mini_keyboard_template.xml +++ b/java/res/xml-sw768dp-land/kbd_more_keys_keyboard_template.xml @@ -21,6 +21,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="3.5%p" latin:rowHeight="@dimen/popup_key_height" - style="?attr/miniKeyboardStyle" + style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-sw768dp-land/kbd_number.xml b/java/res/xml-sw768dp-land/kbd_number.xml new file mode 100644 index 000000000..3ad25a392 --- /dev/null +++ b/java/res/xml-sw768dp-land/kbd_number.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="13.250%p" +> + <include + latin:keyboardLayout="@xml/rows_number" /> +</Keyboard> diff --git a/java/res/xml-ar/kbd_symbols_shift.xml b/java/res/xml-sw768dp-land/kbd_phone.xml index 934e6f849..abe7e7c41 100644 --- a/java/res/xml-ar/kbd_symbols_shift.xml +++ b/java/res/xml-sw768dp-land/kbd_phone.xml @@ -20,8 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:isRtlKeyboard="true" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="13.250%p" > <include - latin:keyboardLayout="@xml/kbd_rows_symbols_shift" /> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-sw768dp-land/kbd_phone_symbols.xml b/java/res/xml-sw768dp-land/kbd_phone_symbols.xml new file mode 100644 index 000000000..641464dbe --- /dev/null +++ b/java/res/xml-sw768dp-land/kbd_phone_symbols.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardHorizontalEdgesPadding="10%p" + latin:keyWidth="13.250%p" +> + <!-- Tablet doesn't have phone symbols keyboard --> + <include + latin:keyboardLayout="@xml/rows_phone" /> +</Keyboard> diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml deleted file mode 100644 index f16f5b6af..000000000 --- a/java/res/xml-sw768dp/kbd_key_styles.xml +++ /dev/null @@ -1,100 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <key-style - latin:styleName="shiftKeyStyle" - latin:code="@integer/key_shift" - latin:keyIcon="iconShiftKey" - latin:keyIconShifted="iconShiftedShiftKey" - latin:backgroundType="sticky" /> - <key-style - latin:styleName="deleteKeyStyle" - latin:code="@integer/key_delete" - latin:keyIcon="iconDeleteKey" - latin:backgroundType="functional" - latin:isRepeatable="true" /> - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyIcon="iconReturnKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="spaceKeyStyle" - latin:code="@integer/key_space" /> - <key-style - latin:styleName="nonSpecialBackgroundSpaceKeyStyle" - latin:code="@integer/key_space" /> - <key-style - latin:styleName="smileyKeyStyle" - latin:keyLabel=":-)" - latin:keyOutputText=":-) " - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_smiley" - latin:maxMoreKeysColumn="5" /> - <key-style - latin:styleName="settingsKeyStyle" - latin:code="@integer/key_settings" - latin:keyIcon="iconSettingsKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="shortcutKeyStyle" - latin:code="@integer/key_shortcut" - latin:keyIcon="iconShortcutKey" - latin:backgroundType="functional" /> - <key-style - latin:styleName="tabKeyStyle" - latin:code="@integer/key_tab" - latin:keyLabel="@string/label_tab_key" - latin:keyLabelOption="fontNormal" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toSymbolKeyStyle" - latin:code="@integer/key_switch_alpha_symbol" - latin:keyLabel="@string/label_to_symbol_key" - latin:keyLabelOption="fontNormal" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toAlphaKeyStyle" - latin:code="@integer/key_switch_alpha_symbol" - latin:keyLabel="@string/label_to_alpha_key" - latin:keyLabelOption="fontNormal" - latin:backgroundType="functional" /> - <key-style - latin:styleName="toMoreSymbolKeyStyle" - latin:code="@integer/key_shift" - latin:keyLabel="@string/label_to_more_symbol_for_tablet_key" - latin:keyLabelOption="fontNormal" - latin:backgroundType="functional" /> - <key-style - latin:styleName="backFromMoreSymbolKeyStyle" - latin:code="@integer/key_shift" - latin:keyLabel="@string/label_to_symbol_key" - latin:keyLabelOption="fontNormal" - latin:backgroundType="functional" /> - <key-style - latin:styleName="comKeyStyle" - latin:keyLabel="@string/keylabel_for_popular_domain" - latin:keyLabelOption="fontNormal|hasPopupHint" - latin:keyOutputText="@string/keylabel_for_popular_domain" - latin:moreKeys="@string/more_keys_for_popular_domain" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_mini_keyboard_template.xml b/java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml index 409c60556..f89a0a673 100644 --- a/java/res/xml-sw768dp/kbd_mini_keyboard_template.xml +++ b/java/res/xml-sw768dp/kbd_more_keys_keyboard_template.xml @@ -21,6 +21,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="5.0%p" latin:rowHeight="@dimen/popup_key_height" - style="?attr/miniKeyboardStyle" + style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-sw768dp/kbd_number.xml b/java/res/xml-sw768dp/kbd_number.xml index 369e91a77..b20123c80 100644 --- a/java/res/xml-sw768dp/kbd_number.xml +++ b/java/res/xml-sw768dp/kbd_number.xml @@ -23,206 +23,5 @@ latin:keyWidth="13.250%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> - <switch> - <case - latin:passwordInput="true" - > - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyStyle="num1KeyStyle" - latin:keyXPos="32.076%p" /> - <Key - latin:keyStyle="num2KeyStyle" /> - <Key - latin:keyStyle="num3KeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="32.076%p" /> - <Key - latin:keyStyle="num4KeyStyle" /> - <Key - latin:keyStyle="num5KeyStyle" /> - <Key - latin:keyStyle="num6KeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="32.076%p" /> - <Key - latin:keyStyle="num7KeyStyle" /> - <Key - latin:keyStyle="num8KeyStyle" /> - <Key - latin:keyStyle="num9KeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <Spacer - latin:keyXPos="32.076%p" /> - <Key - latin:keyStyle="num0KeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - </case> - <!-- latin:passwordInput="false" --> - <default> - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="-" - latin:keyStyle="numKeyStyle" - latin:keyXPos="13.829%p" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="+" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="." - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="1" - latin:keyStyle="numKeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyLabel="2" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="3" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="13.829%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="/" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="," - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="4" - latin:keyStyle="numKeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyLabel="5" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="6" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="(" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel=")" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="=" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="7" - latin:keyStyle="numKeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyLabel="8" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="9" - latin:keyStyle="numKeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <switch> - <case latin:hasSettingsKey="true"> - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - <default> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="8.047%p" /> - </default> - </switch> - <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" - latin:keyXPos="13.829%p" - latin:keyWidth="24.140%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyLabel="0" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="#" - latin:keyStyle="numKeyStyle" /> - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyXPos="-8.047%p" - latin:keyWidth="fillRight" /> - </case> - <default> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </default> - </switch> - </Row> - </default> - </switch> + latin:keyboardLayout="@xml/rows_number" /> </Keyboard> diff --git a/java/res/xml-sw768dp/kbd_phone.xml b/java/res/xml-sw768dp/kbd_phone.xml index e55b1841a..fa9bf1bf4 100644 --- a/java/res/xml-sw768dp/kbd_phone.xml +++ b/java/res/xml-sw768dp/kbd_phone.xml @@ -23,122 +23,5 @@ latin:keyWidth="13.250%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> - <Row> - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="-" - latin:keyStyle="numKeyStyle" - latin:keyXPos="20.400%p" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="+" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyStyle="num1KeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyStyle="num2KeyStyle" /> - <Key - latin:keyStyle="num3KeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="," - latin:keyStyle="numKeyStyle" - latin:keyXPos="20.400%p" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel="." - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyStyle="num4KeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyStyle="num5KeyStyle" /> - <Key - latin:keyStyle="num6KeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-11.172%p" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="20.400%p" /> - <Key - latin:keyLabel="(" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyLabel=")" - latin:keyStyle="numKeyStyle" - latin:keyWidth="8.047%p" /> - <Key - latin:keyStyle="num7KeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyStyle="num8KeyStyle" /> - <Key - latin:keyStyle="num9KeyStyle" /> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </Row> - <Row> - <switch> - <case latin:hasSettingsKey="true"> - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - <default> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="8.047%p" /> - </default> - </switch> - <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" - latin:keyXPos="20.400%p" - latin:keyWidth="16.084%p" /> - <Key - latin:keyStyle="numStarKeyStyle" - latin:keyXPos="43.125%p" /> - <Key - latin:keyStyle="num0KeyStyle" /> - <Key - latin:keyLabel="#" - latin:keyStyle="numKeyStyle" /> - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyXPos="-8.047%p" - latin:keyWidth="fillRight" /> - </case> - <default> - <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> - <Spacer - latin:keyWidth="0%p" /> - </default> - </switch> - </Row> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-da/kbd_qwerty.xml b/java/res/xml-sw768dp/kbd_phone_symbols.xml index 37a50fdfd..e1a359e84 100644 --- a/java/res/xml-da/kbd_qwerty.xml +++ b/java/res/xml-sw768dp/kbd_phone_symbols.xml @@ -20,8 +20,9 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="da" + latin:keyWidth="13.250%p" > + <!-- Tablet doesn't have phone symbols keyboard --> <include - latin:keyboardLayout="@xml/kbd_rows_scandinavian" /> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml-sw768dp/kbd_qwerty_row1.xml b/java/res/xml-sw768dp/kbd_qwerty_row1.xml deleted file mode 100644 index 14b8bddfb..000000000 --- a/java/res/xml-sw768dp/kbd_qwerty_row1.xml +++ /dev/null @@ -1,66 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillBoth"/> - </Row> -</merge> diff --git a/java/res/xml-sw768dp/kbd_qwerty_row2.xml b/java/res/xml-sw768dp/kbd_qwerty_row2.xml deleted file mode 100644 index 2c312a328..000000000 --- a/java/res/xml-sw768dp/kbd_qwerty_row2.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p"/> - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-15.704%p" - latin:keyWidth="fillBoth" /> - </Row> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_arabic.xml b/java/res/xml-sw768dp/kbd_rows_arabic.xml deleted file mode 100644 index 7ec36fd94..000000000 --- a/java/res/xml-sw768dp/kbd_rows_arabic.xml +++ /dev/null @@ -1,193 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.375%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.500%p" /> - <!-- \u0636: ARABIC LETTER DAD --> - <Key - latin:keyLabel="ض" /> - <!-- \u0635: ARABIC LETTER SAD --> - <Key - latin:keyLabel="ص" /> - <!-- \u062b: ARABIC LETTER THEH --> - <Key - latin:keyLabel="ث" /> - <!-- \u0642: ARABIC LETTER QAF - \u06a8: ARABIC LETTER QAF WITH THREE DOTS ABOVE --> - <Key - latin:keyLabel="ق" - latin:moreKeys="ڨ" /> - <!-- \u0641: ARABIC LETTER FEH - \u06a4: ARABIC LETTER VEH - \u06a2: ARABIC LETTER FEH WITH DOT MOVED BELOW - \u06a5: ARABIC LETTER FEH WITH THREE DOTS BELOW --> - <Key - latin:keyLabel="ف" - latin:moreKeys="\u06a4,\u06a2,\u06a5" /> - <!-- \u063a: ARABIC LETTER GHAIN --> - <Key - latin:keyLabel="غ" /> - <!-- \u0639: ARABIC LETTER AIN --> - <Key - latin:keyLabel="ع" /> - <!-- \u0647: ARABIC LETTER HEH - \ufeeb: ARABIC LETTER HEH INITIAL FORM - \u0647\u0640: ARABIC LETTER HEH + Zero width joiner --> - <Key - latin:keyLabel="ه" - latin:moreKeys="\ufeeb|\u0647\u200D" /> - <!-- \u062e: ARABIC LETTER KHAH --> - <Key - latin:keyLabel="خ" /> - <!-- \u062d: ARABIC LETTER HAH --> - <Key - latin:keyLabel="ح" /> - <!-- \u062c: ARABIC LETTER JEEM - \u0686: ARABIC LETTER TCHEH --> - <Key - latin:keyLabel="ج" - latin:moreKeys="چ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.500%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.375%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="9.375%p" /> - <!-- \u0634: ARABIC LETTER SHEEN - \u069c: ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> - <Key - latin:keyLabel="ش" - latin:moreKeys="ڜ" /> - <!-- \u0633: ARABIC LETTER SEEN --> - <Key - latin:keyLabel="س" /> - <!-- \u064a: ARABIC LETTER YEH - \u0626: ARABIC LETTER YEH WITH HAMZA ABOVE - \u0649: ARABIC LETTER ALEF MAKSURA --> - <Key - latin:keyLabel="ي" - latin:moreKeys="\u0626,\u0649" /> - <!-- \u0628: ARABIC LETTER BEH - \u067e: ARABIC LETTER PEH --> - <Key - latin:keyLabel="ب" - latin:moreKeys="پ" /> - <!-- \u0644: ARABIC LETTER LAM - \ufefb: ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM - \u0627: ARABIC LETTER ALEF - \ufef7: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \ufef9: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \ufef5: ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ل" - latin:moreKeys="\ufefb|\u0644\u0627,\ufef7|\u0644\u0623,\ufef9|\u0644\u0625,\ufef5|\u0644\u0622" /> - <!-- \u0627: ARABIC LETTER ALEF - \u0621: ARABIC LETTER HAMZA - \u0671: ARABIC LETTER ALEF WASLA - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ا" - latin:moreKeys="\u0621,\u0671,\u0623,\u0625,\u0622" /> - <!-- \u062a: ARABIC LETTER TEH --> - <Key - latin:keyLabel="ت" /> - <!-- \u0646: ARABIC LETTER NOON --> - <Key - latin:keyLabel="ن" /> - <!-- \u0645: ARABIC LETTER MEEM --> - <Key - latin:keyLabel="م" /> - <!-- \u0643: ARABIC LETTER KAF - \u06af: ARABIC LETTER GAF --> - <Key - latin:keyLabel="ك" - latin:moreKeys="گ" /> - <!-- \u0637: ARABIC LETTER TAH --> - <Key - latin:keyLabel="ط" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-9.375%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.375%p" - > - <!-- \u0626: ARABIC LETTER YEH WITH HAMZA ABOVE --> - <Key - latin:keyLabel="ئ" - latin:keyXPos="12.750%p" /> - <!-- \u0621: ARABIC LETTER HAMZA --> - <Key - latin:keyLabel="ء" /> - <!-- \u0624: ARABIC LETTER WAW WITH HAMZA ABOVE --> - <Key - latin:keyLabel="ؤ" /> - <!-- \u0631: ARABIC LETTER REH --> - <Key - latin:keyLabel="ر" /> - <!-- \u0630: ARABIC LETTER THAL --> - <Key - latin:keyLabel="ذ" /> - <!-- \u0649: ARABIC LETTER ALEF MAKSURA --> - <Key - latin:keyLabel="ى" /> - <!-- \u0629: ARABIC LETTER TEH MARBUTA --> - <Key - latin:keyLabel="ة" /> - <!-- \u0648: ARABIC LETTER WAW --> - <Key - latin:keyLabel="و" /> - <!-- \u0632: ARABIC LETTER ZAIN - \u0698: ARABIC LETTER JEH --> - <Key - latin:keyLabel="ز" - latin:moreKeys="ژ" /> - <!-- \u0638: ARABIC LETTER ZAH --> - <Key - latin:keyLabel="ظ" /> - <!-- \u062f: ARABIC LETTER DAL --> - <Key - latin:keyLabel="د" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_azerty.xml b/java/res/xml-sw768dp/kbd_rows_azerty.xml deleted file mode 100644 index 4659d9924..000000000 --- a/java/res/xml-sw768dp/kbd_rows_azerty.xml +++ /dev/null @@ -1,162 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="10.167%p" /> - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="m" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-15.704%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="\'" - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel=":" - latin:moreKeys=":" /> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> - </case> - <default> - <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> - </default> - </switch> - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_hebrew.xml b/java/res/xml-sw768dp/kbd_rows_hebrew.xml deleted file mode 100644 index 27b39d1ae..000000000 --- a/java/res/xml-sw768dp/kbd_rows_hebrew.xml +++ /dev/null @@ -1,120 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <include - latin:keyboardLayout="@xml/kbd_row4_apostrophe_dash" /> - <Key - latin:keyLabel="ק" /> - <Key - latin:keyLabel="ר" /> - <Key - latin:keyLabel="א" /> - <Key - latin:keyLabel="ט" /> - <Key - latin:keyLabel="ו" /> - <Key - latin:keyLabel="ן" /> - <Key - latin:keyLabel="ם" /> - <Key - latin:keyLabel="פ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-12.000%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="ש" /> - <Key - latin:keyLabel="ד" /> - <Key - latin:keyLabel="ג" - latin:moreKeys="ג׳" /> - <Key - latin:keyLabel="כ" /> - <Key - latin:keyLabel="ע" /> - <Key - latin:keyLabel="י" - latin:moreKeys="ײַ" /> - <Key - latin:keyLabel="ח" - latin:moreKeys="ח׳" /> - <Key - latin:keyLabel="ל" /> - <Key - latin:keyLabel="ך" /> - <Key - latin:keyLabel="ף" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <Key - latin:keyLabel="ז" - latin:moreKeys="ז׳" - latin:keyXPos="13.829%p" /> - <Key - latin:keyLabel="ס" /> - <Key - latin:keyLabel="ב" /> - <Key - latin:keyLabel="ה" /> - <Key - latin:keyLabel="נ" /> - <Key - latin:keyLabel="מ" /> - <Key - latin:keyLabel="צ" - latin:moreKeys="צ׳" /> - <Key - latin:keyLabel="ת" - latin:moreKeys="ת׳" /> - <Key - latin:keyLabel="ץ" - latin:moreKeys="ץ׳" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-10.400%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_qwertz.xml b/java/res/xml-sw768dp/kbd_rows_qwertz.xml deleted file mode 100644 index 82e0dd09c..000000000 --- a/java/res/xml-sw768dp/kbd_rows_qwertz.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <Row - latin:keyWidth="8.047%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> - <switch> - <case - latin:mode="email" - > - <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> - </case> - <default> - <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> - </default> - </switch> - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_russian.xml b/java/res/xml-sw768dp/kbd_rows_russian.xml deleted file mode 100644 index e5f556958..000000000 --- a/java/res/xml-sw768dp/kbd_rows_russian.xml +++ /dev/null @@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.125%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" /> - <Key - latin:keyLabel="й" /> - <Key - latin:keyLabel="ц" /> - <Key - latin:keyLabel="у" /> - <Key - latin:keyLabel="к" /> - <Key - latin:keyLabel="е" - latin:moreKeys="@string/more_keys_for_cyrillic_e" /> - <Key - latin:keyLabel="н" /> - <Key - latin:keyLabel="г" /> - <Key - latin:keyLabel="ш" /> - <Key - latin:keyLabel="щ" /> - <Key - latin:keyLabel="з" /> - <Key - latin:keyLabel="х" /> - <Key - latin:keyLabel="ъ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.125%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="9.375%p" /> - <Key - latin:keyLabel="ф" /> - <Key - latin:keyLabel="ы" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="п" /> - <Key - latin:keyLabel="р" /> - <Key - latin:keyLabel="о" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ж" /> - <Key - latin:keyLabel="э" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-9.375%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.125%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="12.750%p" /> - <Key - latin:keyLabel="я" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="м" /> - <Key - latin:keyLabel="и" /> - <Key - latin:keyLabel="т" /> - <Key - latin:keyLabel="ь" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="ю" /> - <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_scandinavian.xml b/java/res/xml-sw768dp/kbd_rows_scandinavian.xml deleted file mode 100644 index b9d168036..000000000 --- a/java/res/xml-sw768dp/kbd_rows_scandinavian.xml +++ /dev/null @@ -1,145 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.375%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.500%p" /> - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyLabel="å" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-11.500%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.375%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="9.375%p" /> - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_10" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_10" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-9.375%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.375%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="12.750%p" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> - <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyXPos="-12.750%p" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_serbian.xml b/java/res/xml-sw768dp/kbd_rows_serbian.xml deleted file mode 100644 index c07176ef6..000000000 --- a/java/res/xml-sw768dp/kbd_rows_serbian.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="7.125%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" /> - <Key - latin:keyLabel="љ" /> - <Key - latin:keyLabel="њ" /> - <Key - latin:keyLabel="е" /> - <Key - latin:keyLabel="р" /> - <Key - latin:keyLabel="т" /> - <Key - latin:keyLabel="з" /> - <Key - latin:keyLabel="у" /> - <Key - latin:keyLabel="и" /> - <Key - latin:keyLabel="о" /> - <Key - latin:keyLabel="п" /> - <Key - latin:keyLabel="ш" /> - <Key - latin:keyLabel="ђ" /> - <Key - latin:keyLabel="ж" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="7.250%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ф" /> - <Key - latin:keyLabel="г" /> - <Key - latin:keyLabel="х" /> - <Key - latin:keyLabel="ј" /> - <Key - latin:keyLabel="к" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="ћ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="7.250%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="ѕ" /> - <Key - latin:keyLabel="џ" /> - <Key - latin:keyLabel="ц" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="н" /> - <Key - latin:keyLabel="м" /> - <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_spanish.xml b/java/res/xml-sw768dp/kbd_rows_spanish.xml deleted file mode 100644 index c737f400a..000000000 --- a/java/res/xml-sw768dp/kbd_rows_spanish.xml +++ /dev/null @@ -1,70 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="10.167%p" /> - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="ñ" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-15.704%p" - latin:keyWidth="fillBoth" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_symbols.xml b/java/res/xml-sw768dp/kbd_rows_symbols.xml deleted file mode 100644 index 987b10cdc..000000000 --- a/java/res/xml-sw768dp/kbd_rows_symbols.xml +++ /dev/null @@ -1,192 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_1" - latin:moreKeys="@string/more_keys_for_symbols_1" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_2" - latin:moreKeys="@string/more_keys_for_symbols_2" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_3" - latin:moreKeys="@string/more_keys_for_symbols_3" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_4" - latin:moreKeys="@string/more_keys_for_symbols_4" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_5" - latin:moreKeys="@string/more_keys_for_symbols_5" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_6" - latin:moreKeys="@string/more_keys_for_symbols_6" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_7" - latin:moreKeys="@string/more_keys_for_symbols_7" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_8" - latin:moreKeys="@string/more_keys_for_symbols_8" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_9" - latin:moreKeys="@string/more_keys_for_symbols_9" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_0" - latin:moreKeys="@string/more_keys_for_symbols_0" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyLabel="#" /> - <Key - latin:keyStyle="currencyKeyStyle" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_percent" - latin:moreKeys="@string/more_keys_for_symbols_percent" /> - <Key - latin:keyLabel="&" /> - <Key - latin:keyLabel="*" - latin:moreKeys="@string/more_keys_for_star" /> - <Key - latin:keyLabel="-" - latin:moreKeys="_,–,—" /> - <Key - latin:keyLabel="+" - latin:moreKeys="@string/more_keys_for_plus" /> - <Key - latin:keyLabel="(" - latin:moreKeys="[,{,<" /> - <Key - latin:keyLabel=")" - latin:moreKeys="],},>" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-15.704%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="<" - latin:moreKeys="≤,«,‹" /> - <Key - latin:keyLabel=">" - latin:moreKeys="≥,»,›" /> - <Key - latin:keyLabel="=" - latin:moreKeys="≠,≈" /> - <switch> - <case - latin:mode="url" - > - <Key - latin:keyLabel="\'" - latin:moreKeys="‘,’,‚,‛" /> - </case> - <default> - <Key - latin:keyLabel=":" /> - </default> - </switch> - <Key - latin:keyLabel="@string/keylabel_for_symbols_semicolon" - latin:moreKeys="@string/more_keys_for_symbols_semicolon" /> - <Key - latin:keyLabel="@string/keylabel_for_comma" - latin:moreKeys="@string/more_keys_for_comma" /> - <Key - latin:keyLabel="." /> - <Key - latin:keyLabel="!" - latin:moreKeys="¡" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_question" - latin:moreKeys="@string/more_keys_for_symbols_question" /> - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <switch> - <case - latin:hasSettingsKey="true" - > - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - </switch> - <Key - latin:keyLabel="/" - latin:keyXPos="15.157%p" /> - <Key - latin:keyLabel="\@" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="31.250%p" - latin:keyWidth="37.500%p" /> - <!-- Note: DroidSans doesn't have double-high-reversed-quotation '\u201f' glyph. --> - <!-- latin:moreKeys="“,”,„,‟,«,»,‘,’,‚,‛" --> - <Key - latin:keyLabel=""" - latin:moreKeys="“,”,«,»,‘,’,‚,‛" /> - <Key - latin:keyLabel="_" /> - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyXPos="-8.047%p" - latin:keyWidth="fillRight" /> - </case> - </switch> - </Row> -</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml b/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml deleted file mode 100644 index 9a9c3a276..000000000 --- a/java/res/xml-sw768dp/kbd_rows_symbols_shift.xml +++ /dev/null @@ -1,150 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="8.282%p" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="7.969%p" /> - <Key - latin:keyLabel="~" /> - <Key - latin:keyLabel="`" /> - <Key - latin:keyLabel="|" /> - <Key - latin:keyLabel="•" - latin:moreKeys="@string/more_keys_for_bullet" /> - <Key - latin:keyLabel="√" /> - <Key - latin:keyLabel="π" - latin:moreKeys="Π" /> - <Key - latin:keyLabel="÷" /> - <Key - latin:keyLabel="×" /> - <Key - latin:keyLabel="§" - latin:moreKeys="¶" /> - <Key - latin:keyLabel="Δ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyXPos="-9.219%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.125%p" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyLabelOption="alignLeft" - latin:keyWidth="11.172%p" /> - <Key - latin:keyStyle="moreCurrency1KeyStyle" /> - <Key - latin:keyStyle="moreCurrency2KeyStyle" /> - <Key - latin:keyStyle="moreCurrency3KeyStyle" /> - <Key - latin:keyStyle="moreCurrency4KeyStyle" /> - <Key - latin:keyLabel="^" - latin:moreKeys="↑,↓,←,→" /> - <Key - latin:keyLabel="°" - latin:moreKeys="′,″" /> - <Key - latin:keyLabel="±" - latin:moreKeys="∞" /> - <Key - latin:keyLabel="{" /> - <Key - latin:keyLabel="}" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyXPos="-15.704%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyWidth="13.829%p" /> - <Key - latin:keyLabel="\\" /> - <Key - latin:keyLabel="©" /> - <Key - latin:keyLabel="®" /> - <Key - latin:keyLabel="™" /> - <Key - latin:keyLabel="℅" /> - <Key - latin:keyLabel="[" /> - <Key - latin:keyLabel="]" /> - <Key - latin:keyLabel="¡" /> - <Key - latin:keyLabel="¿" /> - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillBoth" /> - </Row> - <Row - latin:keyWidth="8.047%p" - > - <switch> - <case latin:hasSettingsKey="true"> - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="31.250%p" - latin:keyWidth="37.500%p" /> - <switch> - <case - latin:shortcutKeyEnabled="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyXPos="-8.047%p" - latin:keyWidth="fillRight" /> - </case> - </switch> - </Row> -</merge> diff --git a/java/res/xml-sw768dp/key_settings.xml b/java/res/xml-sw768dp/key_settings.xml new file mode 100644 index 000000000..0359a99c5 --- /dev/null +++ b/java/res/xml-sw768dp/key_settings.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:clobberSettingsKey="false" + > + <Key + latin:keyStyle="settingsKeyStyle" /> + </case> + <default> + <Spacer /> + </default> + </switch> + </merge> diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml new file mode 100644 index 000000000..fade151ed --- /dev/null +++ b/java/res/xml-sw768dp/key_styles_common.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <key-style + latin:styleName="hasShiftedLetterHintStyle" + latin:keyLabelFlags="hasShiftedLetterHint|shiftedLetterActivated" /> + </case> + <default> + <key-style + latin:styleName="hasShiftedLetterHintStyle" + latin:keyLabelFlags="hasShiftedLetterHint" /> + </default> + </switch> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted" + > + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> + </case> + <case + latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted" + > + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOn" /> + </case> + <default> + <key-style + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKey" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> + </default> + </switch> + <key-style + latin:styleName="deleteKeyStyle" + latin:code="@integer/key_delete" + latin:keyIcon="iconDeleteKey" + latin:keyActionFlags="isRepeatable|noKeyPreview" + latin:backgroundType="functional" /> + <include + latin:keyboardLayout="@xml/key_styles_enter" /> + <key-style + latin:styleName="spaceKeyStyle" + latin:code="@integer/key_space" + latin:keyActionFlags="noKeyPreview" /> + <key-style + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" /> + <key-style + latin:styleName="smileyKeyStyle" + latin:keyLabel=":-)" + latin:keyOutputText=":-) " + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/more_keys_for_smiley" /> + <key-style + latin:styleName="shortcutKeyStyle" + latin:code="@integer/key_shortcut" + latin:keyIcon="iconShortcutKey" + latin:keyIconDisabled="iconDisabledShortcutKey" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:backgroundType="functional" /> + <key-style + latin:styleName="settingsKeyStyle" + latin:code="@integer/key_settings" + latin:keyIcon="iconSettingsKey" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:backgroundType="functional" /> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + latin:navigatePrevious="true" + > + <key-style + latin:styleName="tabKeyStyle" + latin:code="@integer/key_action_previous" + latin:keyLabel="@string/label_tab_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:backgroundType="functional" /> + </case> + <default> + <key-style + latin:styleName="tabKeyStyle" + latin:code="@integer/key_tab" + latin:keyLabel="@string/label_tab_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:backgroundType="functional" /> + </default> + </switch> + <key-style + latin:styleName="toSymbolKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" + latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="toAlphaKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" + latin:keyLabel="@string/label_to_alpha_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="toMoreSymbolKeyStyle" + latin:code="@integer/key_shift" + latin:keyLabel="@string/label_to_more_symbol_for_tablet_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="backFromMoreSymbolKeyStyle" + latin:code="@integer/key_shift" + latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="fontNormal|preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> + <key-style + latin:styleName="comKeyStyle" + latin:keyLabel="@string/keylabel_for_popular_domain" + latin:keyLabelFlags="fontNormal|hasPopupHint|preserveCase" + latin:keyOutputText="@string/keylabel_for_popular_domain" + latin:moreKeys="@string/more_keys_for_popular_domain" /> +</merge> diff --git a/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw768dp/keys_apostrophe_dash.xml index 9536e81da..a53c1e4ab 100644 --- a/java/res/xml-sw768dp/kbd_row4_apostrophe_dash.xml +++ b/java/res/xml-sw768dp/keys_apostrophe_dash.xml @@ -33,16 +33,16 @@ > <Key latin:keyLabel="/" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel=":" - latin:moreKeys=":" /> + latin:moreKeys=":" + latin:keyStyle="hasShiftedLetterHintStyle" /> </case> <default> <Key latin:keyLabel="@string/keylabel_for_apostrophe" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="@string/keyhintlabel_for_apostrophe" - latin:moreKeys="@string/more_keys_for_apostrophe" /> + latin:moreKeys="@string/more_keys_for_apostrophe" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> <switch> @@ -55,9 +55,9 @@ <default> <Key latin:keyLabel="@string/keylabel_for_dash" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="@string/keyhintlabel_for_dash" - latin:moreKeys="@string/more_keys_for_dash" /> + latin:moreKeys="@string/more_keys_for_dash" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> </merge> diff --git a/java/res/xml-sw768dp/kbd_qwerty_row4.xml b/java/res/xml-sw768dp/row_qwerty4.xml index e35e47d83..0aa04f8f7 100644 --- a/java/res/xml-sw768dp/kbd_qwerty_row4.xml +++ b/java/res/xml-sw768dp/row_qwerty4.xml @@ -24,15 +24,8 @@ <Row latin:keyWidth="8.047%p" > - <switch> - <case - latin:hasSettingsKey="true" - > - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - </switch> + <include + latin:keyboardLayout="@xml/key_settings" /> <Spacer latin:keyXPos="15.157%p" latin:keyWidth="0%p" /> @@ -57,9 +50,9 @@ > <Key latin:keyLabel=":" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="+" - latin:moreKeys="+" /> + latin:moreKeys="+" + latin:keyStyle="hasShiftedLetterHintStyle" /> </case> <default> <Key @@ -76,27 +69,47 @@ <default> <Key latin:keyLabel="/" - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="\@" - latin:moreKeys="\@" /> + latin:moreKeys="\@" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> </default> </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyXPos="31.250%p" - latin:keyWidth="37.500%p" /> + <switch> + <case + latin:languageCode="fa" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="29.453%p" /> + <!-- U+200C: "" ZERO WIDTH NON-JOINER + U+200D: "" ZERO WIDTH JOINER --> + <Key + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" + latin:altCode="@integer/key_space" + latin:keyActionFlags="altCodeWhileTyping" /> + </case> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="37.500%p" /> + </default> + </switch> <switch> <case latin:languageCode="iw" > <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> + latin:keyboardLayout="@xml/keys_comma_period" /> </case> <default> <include - latin:keyboardLayout="@xml/kbd_row4_apostrophe_dash" /> + latin:keyboardLayout="@xml/keys_apostrophe_dash" /> </default> </switch> <switch> diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml new file mode 100644 index 000000000..9901decec --- /dev/null +++ b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillRight" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="10.167%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols3" /> + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml new file mode 100644 index 000000000..b6aa20246 --- /dev/null +++ b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="10.167%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift3" /> + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols_shift4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_arabic.xml b/java/res/xml-sw768dp/rows_arabic.xml new file mode 100644 index 000000000..d5f287e2f --- /dev/null +++ b/java/res/xml-sw768dp/rows_arabic.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.500%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_arabic1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.500%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="9.375%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_arabic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-9.375%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic3" + latin:keyXPos="12.750%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_azerty.xml b/java/res/xml-sw768dp/rows_azerty.xml new file mode 100644 index 000000000..3637ce7d4 --- /dev/null +++ b/java/res/xml-sw768dp/rows_azerty.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_azerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="10.167%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_azerty2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_azerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_bulgarian.xml b/java/res/xml-sw768dp/rows_bulgarian.xml new file mode 100644 index 000000000..5f59f7087 --- /dev/null +++ b/java/res/xml-sw768dp/rows_bulgarian.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.333%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.194%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="9.375%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="14.375%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_east_slavic.xml b/java/res/xml-sw768dp/rows_east_slavic.xml new file mode 100644 index 000000000..ba57b75c4 --- /dev/null +++ b/java/res/xml-sw768dp/rows_east_slavic.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <Key + latin:keyLabel="ъ" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="9.375%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-9.375%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="12.750%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_georgian.xml b/java/res/xml-sw768dp/rows_georgian.xml new file mode 100644 index 000000000..0471e8f1c --- /dev/null +++ b/java/res/xml-sw768dp/rows_georgian.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_georgian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth"/> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_georgian2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_georgian3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_greek.xml b/java/res/xml-sw768dp/rows_greek.xml new file mode 100644 index 000000000..983abe14c --- /dev/null +++ b/java/res/xml-sw768dp/rows_greek.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/key_greek_semicolon" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_greek2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_hebrew.xml b/java/res/xml-sw768dp/rows_hebrew.xml new file mode 100644 index 000000000..891872ccc --- /dev/null +++ b/java/res/xml-sw768dp/rows_hebrew.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/keys_apostrophe_dash" /> + <include + latin:keyboardLayout="@xml/rowkeys_hebrew1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-12.000%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hebrew2" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew3" + latin:keyXPos="13.829%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-10.400%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_nordic.xml b/java/res/xml-sw768dp/rows_nordic.xml new file mode 100644 index 000000000..348972469 --- /dev/null +++ b/java/res/xml-sw768dp/rows_nordic.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.500%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_nordic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.500%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="9.375%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_nordic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-9.375%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="12.750%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-12.750%p" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_number_normal.xml b/java/res/xml-sw768dp/rows_number_normal.xml new file mode 100644 index 000000000..2eeb6c9d4 --- /dev/null +++ b/java/res/xml-sw768dp/rows_number_normal.xml @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <Key + latin:keyLabel="-" + latin:keyStyle="numKeyStyle" + latin:keyXPos="13.829%p" + latin:keyWidth="8.047%p" /> + <Key + latin:keyLabel="+" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + <Key + latin:keyLabel="." + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + <Key + latin:keyLabel="1" + latin:keyStyle="numKeyStyle" + latin:keyXPos="43.125%p" /> + <Key + latin:keyLabel="2" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="3" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.172%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="13.829%p" /> + <Key + latin:keyStyle="numStarKeyStyle" + latin:keyWidth="8.047%p" /> + <Key + latin:keyLabel="/" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + <switch> + <case + latin:mode="time|datetime" + > + <Key + latin:keyLabel="," + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="@string/more_keys_for_am_pm" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + </case> + <default> + <Key + latin:keyLabel="," + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + </default> + </switch> + <Key + latin:keyLabel="4" + latin:keyStyle="numKeyStyle" + latin:keyXPos="43.125%p" /> + <Key + latin:keyLabel="5" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="6" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-11.172%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="13.829%p" /> + <Key + latin:keyLabel="(" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + <Key + latin:keyLabel=")" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + <switch> + <case + latin:mode="time|datetime" + > + <Key + latin:keyLabel=":" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + </case> + <default> + <Key + latin:keyLabel="=" + latin:keyStyle="numKeyStyle" + latin:keyWidth="8.047%p" /> + </default> + </switch> + <Key + latin:keyLabel="7" + latin:keyStyle="numKeyStyle" + latin:keyXPos="43.125%p" /> + <Key + latin:keyLabel="8" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="9" + latin:keyStyle="numKeyStyle" /> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </Row> + <Row> + <include + latin:keyboardLayout="@xml/key_settings" + latin:keyWidth="8.047%p" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="13.829%p" + latin:keyWidth="24.140%p" /> + <Key + latin:keyStyle="numStarKeyStyle" + latin:keyXPos="43.125%p" /> + <Key + latin:keyLabel="0" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="#" + latin:keyStyle="numKeyStyle" /> + <switch> + <case + latin:shortcutKeyEnabled="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" + latin:keyXPos="-8.047%p" + latin:keyWidth="fillRight" /> + </case> + <default> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </default> + </switch> + </Row> +</merge> diff --git a/java/res/xml-sw768dp/rows_number_password.xml b/java/res/xml-sw768dp/rows_number_password.xml new file mode 100644 index 000000000..8acfac6ff --- /dev/null +++ b/java/res/xml-sw768dp/rows_number_password.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> + <Key + latin:keyStyle="numTabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <Key + latin:keyStyle="num1KeyStyle" + latin:keyXPos="32.076%p" /> + <Key + latin:keyStyle="num2KeyStyle" /> + <Key + latin:keyStyle="num3KeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-11.172%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="32.076%p" /> + <Key + latin:keyStyle="num4KeyStyle" /> + <Key + latin:keyStyle="num5KeyStyle" /> + <Key + latin:keyStyle="num6KeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-11.172%p" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="32.076%p" /> + <Key + latin:keyStyle="num7KeyStyle" /> + <Key + latin:keyStyle="num8KeyStyle" /> + <Key + latin:keyStyle="num9KeyStyle" /> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </Row> + <Row> + <Spacer + latin:keyXPos="32.076%p" /> + <Key + latin:keyStyle="num0KeyStyle" /> + <!-- Note: This Spacer prevents the above key from being marked as a right edge key. --> + <Spacer + latin:keyWidth="0%p" /> + </Row> +</merge> diff --git a/java/res/xml-sw768dp/kbd_phone_shift.xml b/java/res/xml-sw768dp/rows_phone.xml index 46f67d311..216fbedfb 100644 --- a/java/res/xml-sw768dp/kbd_phone_shift.xml +++ b/java/res/xml-sw768dp/rows_phone.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2010, The Android Open Source Project +** Copyright 2011, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -18,18 +18,17 @@ */ --> -<Keyboard +<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyWidth="13.250%p" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> + latin:keyboardLayout="@xml/key_styles_common" /> <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> + latin:keyboardLayout="@xml/key_styles_number" /> <Row> <Key - latin:keyStyle="tabKeyStyle" - latin:keyLabelOption="alignLeft" + latin:keyStyle="numTabKeyStyle" + latin:keyLabelFlags="alignLeft" latin:keyWidth="11.172%p" /> <Key latin:keyLabel="-" @@ -41,9 +40,7 @@ latin:keyStyle="numKeyStyle" latin:keyWidth="8.047%p" /> <Key - latin:code="44" - latin:keyLabel="@string/label_pause_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" + latin:keyStyle="numPauseKeyStyle" latin:keyWidth="8.047%p" /> <Key latin:keyStyle="num1KeyStyle" @@ -58,9 +55,9 @@ latin:keyWidth="fillRight" /> </Row> <Row> - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyWidth="11.172%p" /> + <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> + <Spacer + latin:keyWidth="13.829%p" /> <Key latin:keyLabel="," latin:keyStyle="numKeyStyle" @@ -71,9 +68,7 @@ latin:keyStyle="numKeyStyle" latin:keyWidth="8.047%p" /> <Key - latin:code="59" - latin:keyLabel="@string/label_wait_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" + latin:keyStyle="numWaitKeyStyle" latin:keyWidth="8.047%p" /> <Key latin:keyStyle="num4KeyStyle" @@ -83,7 +78,7 @@ <Key latin:keyStyle="num6KeyStyle" /> <Key - latin:keyStyle="returnKeyStyle" + latin:keyStyle="enterKeyStyle" latin:keyXPos="-11.172%p" latin:keyWidth="fillRight" /> </Row> @@ -115,20 +110,11 @@ latin:keyWidth="0%p" /> </Row> <Row> - <switch> - <case latin:hasSettingsKey="true"> - <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="8.047%p" /> - </case> - <default> - <!-- Note: This Spacer prevents the below key from being marked as a left edge key. --> - <Spacer - latin:keyWidth="8.047%p" /> - </default> - </switch> + <include + latin:keyboardLayout="@xml/key_settings" + latin:keyWidth="8.047%p" /> <Key - latin:keyStyle="nonSpecialBackgroundSpaceKeyStyle" + latin:keyStyle="spaceKeyStyle" latin:keyXPos="13.829%p" latin:keyWidth="24.140%p" /> <Key @@ -155,4 +141,4 @@ </default> </switch> </Row> -</Keyboard> +</merge> diff --git a/java/res/xml-sw768dp/rows_qwerty.xml b/java/res/xml-sw768dp/rows_qwerty.xml new file mode 100644 index 000000000..8f0b762c5 --- /dev/null +++ b/java/res/xml-sw768dp/rows_qwerty.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth"/> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_qwertz.xml b/java/res/xml-sw768dp/rows_qwertz.xml new file mode 100644 index 000000000..e3d1c61f0 --- /dev/null +++ b/java/res/xml-sw768dp/rows_qwertz.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwertz1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth"/> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_qwertz3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_south_slavic.xml b/java/res/xml-sw768dp/rows_south_slavic.xml new file mode 100644 index 000000000..0de8ff84c --- /dev/null +++ b/java/res/xml-sw768dp/rows_south_slavic.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.250%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.250%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_spanish.xml b/java/res/xml-sw768dp/rows_spanish.xml new file mode 100644 index 000000000..e4690f396 --- /dev/null +++ b/java/res/xml-sw768dp/rows_spanish.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth"/> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="10.167%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_spanish2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_symbols.xml b/java/res/xml-sw768dp/rows_symbols.xml new file mode 100644 index 000000000..3902aef8e --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillRight" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols3" /> + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_symbols4.xml b/java/res/xml-sw768dp/rows_symbols4.xml new file mode 100644 index 000000000..19b36d690 --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols4.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="8.047%p" + > + <include + latin:keyboardLayout="@xml/key_settings" /> + <Key + latin:keyLabel="/" + latin:keyXPos="15.157%p" /> + <Key + latin:keyLabel="\@" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="37.500%p" /> + <Key + latin:keyLabel=""" + latin:moreKeys="@string/more_keys_for_tablet_double_quote" /> + <Key + latin:keyLabel="_" /> + <switch> + <case + latin:shortcutKeyEnabled="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" + latin:keyXPos="-8.047%p" + latin:keyWidth="fillRight" /> + </case> + </switch> + </Row> +</merge> diff --git a/java/res/xml-sw768dp/rows_symbols_shift.xml b/java/res/xml-sw768dp/rows_symbols_shift.xml new file mode 100644 index 000000000..7cfff3741 --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols_shift.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-9.219%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.125%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyXPos="-15.704%p" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift3" /> + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyXPos="-13.750%p" + latin:keyWidth="fillBoth" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols_shift4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_symbols_shift4.xml b/java/res/xml-sw768dp/rows_symbols_shift4.xml new file mode 100644 index 000000000..8e0071f63 --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols_shift4.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="8.047%p" + > + <include + latin:keyboardLayout="@xml/key_settings" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyXPos="31.250%p" + latin:keyWidth="37.500%p" /> + <switch> + <case + latin:shortcutKeyEnabled="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" + latin:keyXPos="-8.047%p" + latin:keyWidth="fillRight" /> + </case> + </switch> + </Row> +</merge> diff --git a/java/res/xml-tr/kbd_qwerty.xml b/java/res/xml-tr/kbd_qwerty.xml deleted file mode 100644 index d2c38f60a..000000000 --- a/java/res/xml-tr/kbd_qwerty.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, 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. -*/ ---> - -<Keyboard - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="tr" -> - <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> -</Keyboard> diff --git a/java/res/xml-tr/keyboard_set.xml b/java/res/xml-tr/keyboard_set.xml new file mode 100644 index 000000000..da79758ec --- /dev/null +++ b/java/res/xml-tr/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="tr"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-uk/keyboard_set.xml b/java/res/xml-uk/keyboard_set.xml new file mode 100644 index 000000000..a7cfad162 --- /dev/null +++ b/java/res/xml-uk/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="uk"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-vi/keyboard_set.xml b/java/res/xml-vi/keyboard_set.xml new file mode 100644 index 000000000..6d38eb1b4 --- /dev/null +++ b/java/res/xml-vi/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="vi"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-de-rZZ/kbd_qwerty.xml b/java/res/xml/kbd_arabic.xml index d5fd8ef7a..ce5f30b2f 100644 --- a/java/res/xml-de-rZZ/kbd_qwerty.xml +++ b/java/res/xml/kbd_arabic.xml @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="de" > <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> + latin:keyboardLayout="@xml/rows_arabic" /> </Keyboard> diff --git a/java/res/xml-pl/kbd_qwerty.xml b/java/res/xml/kbd_azerty.xml index 44312c52c..7bafe5bca 100644 --- a/java/res/xml-pl/kbd_qwerty.xml +++ b/java/res/xml/kbd_azerty.xml @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="pl" > <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> + latin:keyboardLayout="@xml/rows_azerty" /> </Keyboard> diff --git a/java/res/xml/kbd_azerty_symbols.xml b/java/res/xml/kbd_azerty_symbols.xml new file mode 100644 index 000000000..7e075df48 --- /dev/null +++ b/java/res/xml/kbd_azerty_symbols.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_symbols" /> +</Keyboard> diff --git a/java/res/xml/kbd_azerty_symbols_shift.xml b/java/res/xml/kbd_azerty_symbols_shift.xml new file mode 100644 index 000000000..25db3c84d --- /dev/null +++ b/java/res/xml/kbd_azerty_symbols_shift.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_symbols_shift" /> +</Keyboard> diff --git a/java/res/xml/kbd_bulgarian.xml b/java/res/xml/kbd_bulgarian.xml new file mode 100644 index 000000000..a651991c0 --- /dev/null +++ b/java/res/xml/kbd_bulgarian.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"): +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_bulgarian" /> +</Keyboard> diff --git a/java/res/xml/kbd_east_slavic.xml b/java/res/xml/kbd_east_slavic.xml new file mode 100644 index 000000000..3bc233953 --- /dev/null +++ b/java/res/xml/kbd_east_slavic.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_east_slavic" /> +</Keyboard> diff --git a/java/res/xml/kbd_georgian.xml b/java/res/xml/kbd_georgian.xml new file mode 100644 index 000000000..2dc6bf0ee --- /dev/null +++ b/java/res/xml/kbd_georgian.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_georgian" /> +</Keyboard> diff --git a/java/res/xml/kbd_greek.xml b/java/res/xml/kbd_greek.xml new file mode 100644 index 000000000..7056efb00 --- /dev/null +++ b/java/res/xml/kbd_greek.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_greek" /> +</Keyboard> diff --git a/java/res/xml-hu/kbd_qwerty.xml b/java/res/xml/kbd_hebrew.xml index 3195d5b1f..74836f342 100644 --- a/java/res/xml-hu/kbd_qwerty.xml +++ b/java/res/xml/kbd_hebrew.xml @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="hu" > <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> + latin:keyboardLayout="@xml/rows_hebrew" /> </Keyboard> diff --git a/java/res/xml/kbd_mini_keyboard_template.xml b/java/res/xml/kbd_more_keys_keyboard_template.xml index ad6cf51fe..8e977c5ad 100644 --- a/java/res/xml/kbd_mini_keyboard_template.xml +++ b/java/res/xml/kbd_more_keys_keyboard_template.xml @@ -21,6 +21,6 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" latin:keyWidth="10%p" latin:rowHeight="@dimen/popup_key_height" - style="?attr/miniKeyboardStyle" + style="?attr/moreKeysKeyboardStyle" > </Keyboard> diff --git a/java/res/xml-cs/kbd_qwerty.xml b/java/res/xml/kbd_nordic.xml index 9991ea2d2..a2196c926 100644 --- a/java/res/xml-cs/kbd_qwerty.xml +++ b/java/res/xml/kbd_nordic.xml @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="cs" > <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> + latin:keyboardLayout="@xml/rows_nordic" /> </Keyboard> diff --git a/java/res/xml/kbd_number.xml b/java/res/xml/kbd_number.xml index 38dd6bf62..8b0deea97 100644 --- a/java/res/xml/kbd_number.xml +++ b/java/res/xml/kbd_number.xml @@ -23,5 +23,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_number" /> + latin:keyboardLayout="@xml/rows_number" /> </Keyboard> diff --git a/java/res/xml/kbd_phone.xml b/java/res/xml/kbd_phone.xml index b550f17c5..91637b62c 100644 --- a/java/res/xml/kbd_phone.xml +++ b/java/res/xml/kbd_phone.xml @@ -23,5 +23,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_phone" /> + latin:keyboardLayout="@xml/rows_phone" /> </Keyboard> diff --git a/java/res/xml/kbd_phone_shift.xml b/java/res/xml/kbd_phone_symbols.xml index eea823fc0..7f59a855a 100644 --- a/java/res/xml/kbd_phone_shift.xml +++ b/java/res/xml/kbd_phone_symbols.xml @@ -23,5 +23,5 @@ latin:keyWidth="26.67%p" > <include - latin:keyboardLayout="@xml/kbd_rows_phone_shift" /> + latin:keyboardLayout="@xml/rows_phone_symbols" /> </Keyboard> diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml index 40917b921..2f49b943a 100644 --- a/java/res/xml/kbd_qwerty.xml +++ b/java/res/xml/kbd_qwerty.xml @@ -20,8 +20,7 @@ <Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="en_GB,en_US" > <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> + latin:keyboardLayout="@xml/rows_qwerty" /> </Keyboard> diff --git a/java/res/xml/kbd_qwerty_f1.xml b/java/res/xml/kbd_qwerty_f1.xml deleted file mode 100644 index 83b6ecc8d..000000000 --- a/java/res/xml/kbd_qwerty_f1.xml +++ /dev/null @@ -1,94 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <switch> - <case - latin:hasSettingsKey="false" - latin:navigateAction="false" - > - <switch> - <case - latin:mode="url" - > - <Key - latin:keyLabel="/" - latin:keyStyle="f1PopupStyle" /> - </case> - <case - latin:mode="email" - > - <Key - latin:keyLabel="\@" - latin:keyStyle="f1PopupStyle" /> - </case> - <case - latin:hasShortcutKey="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" /> - </case> - <!-- latin:hasShortcutKey="false" --> - <default> - <Key - latin:keyLabel="@string/keylabel_for_comma" - latin:keyStyle="f1PopupStyle" /> - </default> - </switch> - </case> - <!-- hasSettingsKey="true" or navigateAction="true" --> - <default> - <switch> - <case - latin:mode="url" - > - <Key - latin:keyLabel="/" - latin:keyWidth="9.2%p" - latin:keyStyle="f1PopupStyle" /> - </case> - <case - latin:mode="email" - > - <Key - latin:keyLabel="\@" - latin:keyWidth="9.2%p" - latin:keyStyle="f1PopupStyle" /> - </case> - <case - latin:hasShortcutKey="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyWidth="9.2%p" /> - </case> - <!-- hasShortcutKey="false" --> - <default> - <Key - latin:keyLabel="@string/keylabel_for_comma" - latin:keyWidth="9.2%p" - latin:keyStyle="f1PopupStyle" /> - </default> - </switch> - </default> - </switch> -</merge> diff --git a/java/res/xml/kbd_qwerty_row1.xml b/java/res/xml/kbd_qwerty_row1.xml deleted file mode 100644 index e8e8d1b46..000000000 --- a/java/res/xml/kbd_qwerty_row1.xml +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="q" - latin:keyHintLabel="1" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:keyHintLabel="2" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:keyHintLabel="3" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:keyHintLabel="4" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:keyHintLabel="5" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:keyHintLabel="6" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:keyHintLabel="7" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:keyHintLabel="8" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:keyHintLabel="9" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:keyHintLabel="0" - latin:moreKeys="@string/more_keys_for_p" - latin:keyWidth="fillRight" /> - </Row> -</merge> diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml deleted file mode 100644 index eb1e9b8b3..000000000 --- a/java/res/xml/kbd_qwerty_row4.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="10%p" - > - <switch> - <case - latin:hasSettingsKey="false" - latin:navigateAction="false" - > - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyWidth="15%p" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f1" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="50%p" /> - <Key - latin:keyStyle="punctuationKeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </case> - <!-- hasSettingsKey="true" or navigateAction="true" --> - <default> - <Key - latin:keyStyle="toSymbolKeyStyle" - latin:keyWidth="13.75%p" /> - <include - latin:keyboardLayout="@xml/kbd_settings_or_tab" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f1" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="35.83%p" /> - <Key - latin:keyStyle="punctuationKeyStyle" - latin:keyWidth="9.2%p" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </default> - </switch> - </Row> -</merge> diff --git a/java/res/xml/kbd_qwertz.xml b/java/res/xml/kbd_qwertz.xml new file mode 100644 index 000000000..9f7e9019c --- /dev/null +++ b/java/res/xml/kbd_qwertz.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_qwertz" /> +</Keyboard> diff --git a/java/res/xml/kbd_rows_arabic.xml b/java/res/xml/kbd_rows_arabic.xml deleted file mode 100644 index dd5123e4c..000000000 --- a/java/res/xml/kbd_rows_arabic.xml +++ /dev/null @@ -1,189 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <!-- \u0636: ARABIC LETTER DAD --> - <Key - latin:keyLabel="ض" - latin:keyHintLabel="1" - latin:moreKeys="1,١" /> - <!-- \u0635: ARABIC LETTER SAD --> - <Key - latin:keyLabel="ص" - latin:keyHintLabel="2" - latin:moreKeys="2,٢" /> - <!-- \u0642: ARABIC LETTER QAF - \u06a8: ARABIC LETTER QAF WITH THREE DOTS ABOVE --> - <Key - latin:keyLabel="ق" - latin:keyHintLabel="3" - latin:moreKeys="3,٣,\u06a8" /> - <!-- \u0641: ARABIC LETTER FEH - \u06a4: ARABIC LETTER VEH - \u06a2: ARABIC LETTER FEH WITH DOT MOVED BELOW - \u06a5: ARABIC LETTER FEH WITH THREE DOTS BELOW --> - <Key - latin:keyLabel="ف" - latin:keyHintLabel="4" - latin:moreKeys="4,٤,\u06a4,\u06a2,\u06a5" /> - <!-- \u063a: ARABIC LETTER GHAIN --> - <Key - latin:keyLabel="غ" - latin:keyHintLabel="5" - latin:moreKeys="5,٥" /> - <!-- \u0639: ARABIC LETTER AIN --> - <Key - latin:keyLabel="ع" - latin:keyHintLabel="6" - latin:moreKeys="6,٦" /> - <!-- \u0647: ARABIC LETTER HEH - \ufeeb: ARABIC LETTER HEH INITIAL FORM - \u0647\u0640: ARABIC LETTER HEH + Zero width joiner --> - <Key - latin:keyLabel="ه" - latin:keyHintLabel="7" - latin:moreKeys="7,٧,\ufeeb|\u0647\u200D" /> - <!-- \u062e: ARABIC LETTER KHAH --> - <Key - latin:keyLabel="خ" - latin:keyHintLabel="8" - latin:moreKeys="8,٨" /> - <!-- \u062d: ARABIC LETTER HAH --> - <Key - latin:keyLabel="ح" - latin:keyHintLabel="9" - latin:moreKeys="9,٩" /> - <!-- \u062c: ARABIC LETTER JEEM - \u0686: ARABIC LETTER TCHEH --> - <Key - latin:keyLabel="ج" - latin:keyHintLabel="0" - latin:moreKeys="0,٠,\u0686" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <!-- \u0634: ARABIC LETTER SHEEN - \u069c: ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> - <Key - latin:keyLabel="ش" - latin:moreKeys="ڜ" /> - <!-- \u0633: ARABIC LETTER SEEN --> - <Key - latin:keyLabel="س" /> - <!-- \u064a: ARABIC LETTER YEH - \u0626: ARABIC LETTER YEH WITH HAMZA ABOVE - \u0649: ARABIC LETTER ALEF MAKSURA --> - <Key - latin:keyLabel="ي" - latin:moreKeys="\u0626,\u0649" /> - <!-- \u0628: ARABIC LETTER BEH - \u067e: ARABIC LETTER PEH --> - <Key - latin:keyLabel="ب" - latin:moreKeys="پ" /> - <!-- \u0644: ARABIC LETTER LAM - \ufefb: ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM - \u0627: ARABIC LETTER ALEF - \ufef7: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \ufef9: ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \ufef5: ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ل" - latin:moreKeys="\ufefb|\u0644\u0627,\ufef7|\u0644\u0623,\ufef9|\u0644\u0625,\ufef5|\u0644\u0622" /> - <!-- \u0627: ARABIC LETTER ALEF - \u0621: ARABIC LETTER HAMZA - \u0671: ARABIC LETTER ALEF WASLA - \u0623: ARABIC LETTER ALEF WITH HAMZA ABOVE - \u0625: ARABIC LETTER ALEF WITH HAMZA BELOW - \u0622: ARABIC LETTER ALEF WITH MADDA ABOVE --> - <Key - latin:keyLabel="ا" - latin:moreKeys="\u0621,\u0671,\u0623,\u0625,\u0622" /> - <!-- \u062a: ARABIC LETTER TEH - \u062b: ARABIC LETTER THEH --> - <Key - latin:keyLabel="ت" - latin:moreKeys="ث" /> - <!-- \u0646: ARABIC LETTER NOON --> - <Key - latin:keyLabel="ن" /> - <!-- \u0645: ARABIC LETTER MEEM --> - <Key - latin:keyLabel="م" /> - <!-- \u0643: ARABIC LETTER KAF - \u06af: ARABIC LETTER GAF - \u06a9: ARABIC LETTER KEHEH --> - <Key - latin:keyLabel="ك" - latin:moreKeys="\u06af,\u06a9" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <!-- \u0638: ARABIC LETTER ZAH --> - <Key - latin:keyLabel="ظ" - latin:keyXPos="5.0%p" /> - <!-- \u0637: ARABIC LETTER TAH --> - <Key - latin:keyLabel="ط" /> - <!-- \u0630: ARABIC LETTER THAL --> - <Key - latin:keyLabel="ذ" /> - <!-- \u062f: ARABIC LETTER DAL --> - <Key - latin:keyLabel="د" /> - <!-- \u0632: ARABIC LETTER ZAIN - \u0698: ARABIC LETTER JEH --> - <Key - latin:keyLabel="ز" - latin:moreKeys="ژ" /> - <!-- \u0631: ARABIC LETTER REH --> - <Key - latin:keyLabel="ر" /> - <!-- \u0629: ARABIC LETTER TEH MARBUTA --> - <Key - latin:keyLabel="ة" /> - <!-- \u0648: ARABIC LETTER WAW - \u0624: ARABIC LETTER WAW WITH HAMZA ABOVE --> - <Key - latin:keyLabel="و" - latin:moreKeys="ؤ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_azerty.xml b/java/res/xml/kbd_rows_azerty.xml deleted file mode 100644 index 54fe546e3..000000000 --- a/java/res/xml/kbd_rows_azerty.xml +++ /dev/null @@ -1,136 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="a" - latin:keyHintLabel="1" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="z" - latin:keyHintLabel="2" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="e" - latin:keyHintLabel="3" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:keyHintLabel="4" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:keyHintLabel="5" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:keyHintLabel="6" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:keyHintLabel="7" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:keyHintLabel="8" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:keyHintLabel="9" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:keyHintLabel="0" - latin:moreKeys="@string/more_keys_for_p" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="q" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="m" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="15%p" - latin:visualInsetsRight="1%p" /> - <Key - latin:keyLabel="w" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="\'" - latin:moreKeys="‘,’,‚,‛" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_hebrew.xml b/java/res/xml/kbd_rows_hebrew.xml deleted file mode 100644 index 6be8174c5..000000000 --- a/java/res/xml/kbd_rows_hebrew.xml +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="ק" - latin:keyXPos="5%p" /> - <Key - latin:keyLabel="ר" /> - <Key - latin:keyLabel="א" /> - <Key - latin:keyLabel="ט" /> - <Key - latin:keyLabel="ו" /> - <Key - latin:keyLabel="ן" /> - <Key - latin:keyLabel="ם" /> - <Key - latin:keyLabel="פ" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="ש" /> - <Key - latin:keyLabel="ד" /> - <Key - latin:keyLabel="ג" - latin:moreKeys="ג׳" /> - <Key - latin:keyLabel="כ" /> - <Key - latin:keyLabel="ע" /> - <Key - latin:keyLabel="י" - latin:moreKeys="ײַ" /> - <Key - latin:keyLabel="ח" - latin:moreKeys="ח׳" /> - <Key - latin:keyLabel="ל" /> - <Key - latin:keyLabel="ך" /> - <Key - latin:keyLabel="ף" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="ז" - latin:moreKeys="ז׳" - latin:keyXPos="5%p" /> - <Key - latin:keyLabel="ס" /> - <Key - latin:keyLabel="ב" /> - <Key - latin:keyLabel="ה" /> - <Key - latin:keyLabel="נ" /> - <Key - latin:keyLabel="מ" /> - <Key - latin:keyLabel="צ" - latin:moreKeys="צ׳" /> - <Key - latin:keyLabel="ת" - latin:moreKeys="ת׳" /> - <Key - latin:keyLabel="ץ" - latin:moreKeys="ץ׳" /> - <!-- Here is 5%p space --> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_number.xml b/java/res/xml/kbd_rows_number.xml deleted file mode 100644 index 90ac5686b..000000000 --- a/java/res/xml/kbd_rows_number.xml +++ /dev/null @@ -1,132 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> - <switch> - <case - latin:passwordInput="true" - > - <Row> - <Key - latin:keyStyle="num1KeyStyle" /> - <Key - latin:keyStyle="num2KeyStyle" /> - <Key - latin:keyStyle="num3KeyStyle" /> - <Spacer /> - </Row> - <Row> - <Key - latin:keyStyle="num4KeyStyle" /> - <Key - latin:keyStyle="num5KeyStyle" /> - <Key - latin:keyStyle="num6KeyStyle" /> - <Spacer /> - </Row> - <Row> - <Key - latin:keyStyle="num7KeyStyle" /> - <Key - latin:keyStyle="num8KeyStyle" /> - <Key - latin:keyStyle="num9KeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <Spacer /> - <Key - latin:keyStyle="num0KeyStyle" /> - <Spacer /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - </case> - <!-- latin:passwordInput="false" --> - <default> - <Row> - <Key - latin:keyLabel="1" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="2" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="3" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="-" - latin:keyStyle="numFunctionalKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <Key - latin:keyLabel="4" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="5" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="6" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="," - latin:keyStyle="numFunctionalKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <Key - latin:keyLabel="7" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="8" - latin:keyStyle="numKeyStyle"/> - <Key - latin:keyLabel="9" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <Row> - <Key - latin:keyStyle="numSpaceKeyStyle" /> - <Key - latin:keyLabel="0" - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyLabel="." - latin:keyStyle="numKeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - </default> - </switch> -</merge> diff --git a/java/res/xml/kbd_rows_qwertz.xml b/java/res/xml/kbd_rows_qwertz.xml deleted file mode 100644 index 71bb601e6..000000000 --- a/java/res/xml/kbd_rows_qwertz.xml +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="q" - latin:keyHintLabel="1" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:keyHintLabel="2" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:keyHintLabel="3" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:keyHintLabel="4" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:keyHintLabel="5" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="z" - latin:keyHintLabel="6" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="u" - latin:keyHintLabel="7" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:keyHintLabel="8" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:keyHintLabel="9" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:keyHintLabel="0" - latin:moreKeys="@string/more_keys_for_p" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="15%p" - latin:visualInsetsRight="1%p" /> - <Key - latin:keyLabel="y" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_russian.xml b/java/res/xml/kbd_rows_russian.xml deleted file mode 100644 index f1794e750..000000000 --- a/java/res/xml/kbd_rows_russian.xml +++ /dev/null @@ -1,133 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="й" - latin:keyHintLabel="1" - latin:moreKeys="1" /> - <Key - latin:keyLabel="ц" - latin:keyHintLabel="2" - latin:moreKeys="2" /> - <Key - latin:keyLabel="у" - latin:keyHintLabel="3" - latin:moreKeys="3" /> - <Key - latin:keyLabel="к" - latin:keyHintLabel="4" - latin:moreKeys="4" /> - <Key - latin:keyLabel="е" - latin:keyHintLabel="5" - latin:moreKeys="@string/more_keys_for_cyrillic_e" /> - <Key - latin:keyLabel="н" - latin:keyHintLabel="6" - latin:moreKeys="6" /> - <Key - latin:keyLabel="г" - latin:keyHintLabel="7" - latin:moreKeys="7" /> - <Key - latin:keyLabel="ш" - latin:keyHintLabel="8" - latin:moreKeys="8" /> - <Key - latin:keyLabel="щ" - latin:keyHintLabel="9" - latin:moreKeys="9" /> - <Key - latin:keyLabel="з" - latin:keyHintLabel="0" - latin:moreKeys="0" /> - <Key - latin:keyLabel="х" - latin:moreKeys="@string/more_keys_for_cyrillic_ha" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="ф" - latin:keyWidth="8.75%p" /> - <Key - latin:keyLabel="ы" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="п" /> - <Key - latin:keyLabel="р" /> - <Key - latin:keyLabel="о" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ж" /> - <Key - latin:keyLabel="э" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="11.75%p" /> - <Key - latin:keyLabel="я" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="м" /> - <Key - latin:keyLabel="и" /> - <Key - latin:keyLabel="т" /> - <Key - latin:keyLabel="ь" - latin:moreKeys="@string/more_keys_for_cyrillic_soft_sign" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="ю" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_scandinavian.xml b/java/res/xml/kbd_rows_scandinavian.xml deleted file mode 100644 index 4f138c514..000000000 --- a/java/res/xml/kbd_rows_scandinavian.xml +++ /dev/null @@ -1,113 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="q" - latin:keyHintLabel="1" - latin:moreKeys="@string/more_keys_for_q" /> - <Key - latin:keyLabel="w" - latin:keyHintLabel="2" - latin:moreKeys="@string/more_keys_for_w" /> - <Key - latin:keyLabel="e" - latin:keyHintLabel="3" - latin:moreKeys="@string/more_keys_for_e" /> - <Key - latin:keyLabel="r" - latin:keyHintLabel="4" - latin:moreKeys="@string/more_keys_for_r" /> - <Key - latin:keyLabel="t" - latin:keyHintLabel="5" - latin:moreKeys="@string/more_keys_for_t" /> - <Key - latin:keyLabel="y" - latin:keyHintLabel="6" - latin:moreKeys="@string/more_keys_for_y" /> - <Key - latin:keyLabel="u" - latin:keyHintLabel="7" - latin:moreKeys="@string/more_keys_for_u" /> - <Key - latin:keyLabel="i" - latin:keyHintLabel="8" - latin:moreKeys="@string/more_keys_for_i" /> - <Key - latin:keyLabel="o" - latin:keyHintLabel="9" - latin:moreKeys="@string/more_keys_for_o" /> - <Key - latin:keyLabel="p" - latin:keyHintLabel="0" - latin:moreKeys="@string/more_keys_for_p" /> - <Key - latin:keyLabel="å" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" - latin:keyWidth="8.75%p" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_10" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_10" /> - <Key - latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" - latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_serbian.xml b/java/res/xml/kbd_rows_serbian.xml deleted file mode 100644 index da4d69521..000000000 --- a/java/res/xml/kbd_rows_serbian.xml +++ /dev/null @@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="љ" - latin:keyHintLabel="1" - latin:moreKeys="1" /> - <Key - latin:keyLabel="њ" - latin:keyHintLabel="2" - latin:moreKeys="2" /> - <Key - latin:keyLabel="е" - latin:keyHintLabel="3" - latin:moreKeys="3" /> - <Key - latin:keyLabel="р" - latin:keyHintLabel="4" - latin:moreKeys="4" /> - <Key - latin:keyLabel="т" - latin:keyHintLabel="5" - latin:moreKeys="5" /> - <Key - latin:keyLabel="з" - latin:keyHintLabel="6" - latin:moreKeys="6" /> - <Key - latin:keyLabel="у" - latin:keyHintLabel="7" - latin:moreKeys="7" /> - <Key - latin:keyLabel="и" - latin:keyHintLabel="8" - latin:moreKeys="8" /> - <Key - latin:keyLabel="о" - latin:keyHintLabel="9" - latin:moreKeys="9" /> - <Key - latin:keyLabel="п" - latin:keyHintLabel="0" - latin:moreKeys="0" /> - <Key - latin:keyLabel="ш" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="9.091%p" - > - <Key - latin:keyLabel="а" /> - <Key - latin:keyLabel="с" /> - <Key - latin:keyLabel="д" /> - <Key - latin:keyLabel="ф" /> - <Key - latin:keyLabel="г" /> - <Key - latin:keyLabel="х" /> - <Key - latin:keyLabel="ј" /> - <Key - latin:keyLabel="к" /> - <Key - latin:keyLabel="л" /> - <Key - latin:keyLabel="ч" /> - <Key - latin:keyLabel="ћ" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="8.5%p" - > - <Key - latin:keyStyle="shiftKeyStyle" - latin:keyWidth="11.75%p" /> - <Key - latin:keyLabel="ѕ" /> - <Key - latin:keyLabel="џ" /> - <Key - latin:keyLabel="ц" /> - <Key - latin:keyLabel="в" /> - <Key - latin:keyLabel="б" /> - <Key - latin:keyLabel="н" /> - <Key - latin:keyLabel="м" /> - <Key - latin:keyLabel="ђ" /> - <Key - latin:keyLabel="ж" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_spanish.xml b/java/res/xml/kbd_rows_spanish.xml deleted file mode 100644 index 03d631ee0..000000000 --- a/java/res/xml/kbd_rows_spanish.xml +++ /dev/null @@ -1,62 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" /> - <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> - <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <Key - latin:keyLabel="ñ" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_symbols.xml b/java/res/xml/kbd_rows_symbols.xml deleted file mode 100644 index c5bcb14c3..000000000 --- a/java/res/xml/kbd_rows_symbols.xml +++ /dev/null @@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2011, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="@string/keylabel_for_symbols_1" - latin:moreKeys="@string/more_keys_for_symbols_1" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_2" - latin:moreKeys="@string/more_keys_for_symbols_2" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_3" - latin:moreKeys="@string/more_keys_for_symbols_3" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_4" - latin:moreKeys="@string/more_keys_for_symbols_4" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_5" - latin:moreKeys="@string/more_keys_for_symbols_5" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_6" - latin:moreKeys="@string/more_keys_for_symbols_6" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_7" - latin:moreKeys="@string/more_keys_for_symbols_7" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_8" - latin:moreKeys="@string/more_keys_for_symbols_8" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_9" - latin:moreKeys="@string/more_keys_for_symbols_9" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_0" - latin:moreKeys="@string/more_keys_for_symbols_0" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="\@" /> - <Key - latin:keyLabel="\#" /> - <Key - latin:keyStyle="currencyKeyStyle" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_percent" - latin:moreKeys="@string/more_keys_for_symbols_percent" /> - <Key - latin:keyLabel="&" /> - <Key - latin:keyLabel="*" - latin:moreKeys="@string/more_keys_for_star" /> - <Key - latin:keyLabel="-" - latin:moreKeys="_,–,—" /> - <Key - latin:keyLabel="+" - latin:moreKeys="@string/more_keys_for_plus" /> - <Key - latin:keyLabel="(" - latin:moreKeys="@string/more_keys_for_left_parenthesis" /> - <Key - latin:keyLabel=")" - latin:moreKeys="@string/more_keys_for_right_parenthesis" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyStyle="toMoreSymbolKeyStyle" - latin:keyWidth="15%p" - latin:visualInsetsRight="1%p" /> - <Key - latin:keyLabel="!" - latin:moreKeys="¡" /> - <!-- Note: Neither DroidSans nor Roboto have a glyph for ‟ Double high-reversed-9 quotation mark U+201F. --> - <!-- latin:moreKeys="“,”,„,‟,«,»" --> - <Key - latin:keyLabel=""" - latin:moreKeys="“,”,«,»" - latin:maxMoreKeysColumn="6" /> - <Key - latin:keyLabel="\'" - latin:moreKeys="‘,’,‚,‛" /> - <Key - latin:keyLabel=":" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_semicolon" - latin:moreKeys="@string/more_keys_for_symbols_semicolon" /> - <Key - latin:keyLabel="/" /> - <Key - latin:keyLabel="@string/keylabel_for_symbols_question" - latin:moreKeys="@string/more_keys_for_symbols_question" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_symbols_row4" /> -</merge> diff --git a/java/res/xml/kbd_rows_symbols_shift.xml b/java/res/xml/kbd_rows_symbols_shift.xml deleted file mode 100644 index 91654b04b..000000000 --- a/java/res/xml/kbd_rows_symbols_shift.xml +++ /dev/null @@ -1,114 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_currency_key_styles" /> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyLabel="~" /> - <Key - latin:keyLabel="`" /> - <Key - latin:keyLabel="|" /> - <Key - latin:keyLabel="•" - latin:moreKeys="@string/more_keys_for_bullet" /> - <Key - latin:keyLabel="√" /> - <Key - latin:keyLabel="π" - latin:moreKeys="Π" /> - <Key - latin:keyLabel="÷" /> - <Key - latin:keyLabel="×" /> - <Key - latin:keyLabel="{" /> - <Key - latin:keyLabel="}" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyStyle="nonSpecialBackgroundTabKeyStyle" /> - <Key - latin:keyStyle="moreCurrency1KeyStyle" /> - <Key - latin:keyStyle="moreCurrency2KeyStyle" /> - <Key - latin:keyStyle="moreCurrency3KeyStyle" /> - <Key - latin:keyLabel="°" - latin:moreKeys="′,″" /> - <Key - latin:keyLabel="^" - latin:moreKeys="↑,↓,←,→" /> - <Key - latin:keyLabel="_" /> - <Key - latin:keyLabel="=" - latin:moreKeys="≠,≈,∞" /> - <Key - latin:keyLabel="[" /> - <Key - latin:keyLabel="]" - latin:keyWidth="fillRight" /> - </Row> - <Row - latin:keyWidth="10%p" - > - <Key - latin:keyStyle="backFromMoreSymbolKeyStyle" - latin:keyWidth="15%p" - latin:visualInsetsRight="1%p" /> - <Key - latin:keyLabel="™" /> - <Key - latin:keyLabel="®" /> - <Key - latin:keyLabel="©" /> - <Key - latin:keyLabel="¶" - latin:moreKeys="§" /> - <Key - latin:keyLabel="\\" /> - <Key - latin:keyLabel="<" - latin:moreKeys="≤,«,‹" /> - <Key - latin:keyLabel=">" - latin:moreKeys="≥,»,›" /> - <Key - latin:keyStyle="deleteKeyStyle" - latin:keyWidth="fillRight" - latin:visualInsetsLeft="1%p" /> - </Row> - <include - latin:keyboardLayout="@xml/kbd_symbols_shift_row4" /> -</merge> diff --git a/java/res/xml/kbd_south_slavic.xml b/java/res/xml/kbd_south_slavic.xml new file mode 100644 index 000000000..f3ad02c7b --- /dev/null +++ b/java/res/xml/kbd_south_slavic.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_south_slavic" /> +</Keyboard> diff --git a/java/res/xml/kbd_spanish.xml b/java/res/xml/kbd_spanish.xml new file mode 100644 index 000000000..6ce2b5d24 --- /dev/null +++ b/java/res/xml/kbd_spanish.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, 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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_spanish" /> +</Keyboard> diff --git a/java/res/xml/kbd_spanish_symbols.xml b/java/res/xml/kbd_spanish_symbols.xml new file mode 100644 index 000000000..7e075df48 --- /dev/null +++ b/java/res/xml/kbd_spanish_symbols.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_symbols" /> +</Keyboard> diff --git a/java/res/xml/kbd_spanish_symbols_shift.xml b/java/res/xml/kbd_spanish_symbols_shift.xml new file mode 100644 index 000000000..25db3c84d --- /dev/null +++ b/java/res/xml/kbd_spanish_symbols_shift.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rows_symbols_shift" /> +</Keyboard> diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml index 737f684a7..f6612a2f7 100644 --- a/java/res/xml/kbd_symbols.xml +++ b/java/res/xml/kbd_symbols.xml @@ -22,5 +22,5 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:keyboardLayout="@xml/kbd_rows_symbols" /> + latin:keyboardLayout="@xml/rows_symbols" /> </Keyboard> diff --git a/java/res/xml/kbd_symbols_f1.xml b/java/res/xml/kbd_symbols_f1.xml deleted file mode 100644 index 0dd3d9109..000000000 --- a/java/res/xml/kbd_symbols_f1.xml +++ /dev/null @@ -1,64 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <switch> - <case - latin:hasSettingsKey="false" - latin:navigateAction="false" - > - <switch> - <case - latin:hasShortcutKey="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" /> - </case> - <!-- latin:hasShortcutKey="false" --> - <default> - <Key - latin:keyLabel="@string/keylabel_for_f1" - latin:keyStyle="f1PopupStyle" /> - </default> - </switch> - </case> - <!-- hasSettingsKey="true" or navigateAction="true" --> - <default> - <switch> - <case - latin:hasShortcutKey="true" - > - <Key - latin:keyStyle="shortcutKeyStyle" - latin:keyWidth="9.2%p" /> - </case> - <!-- latin:hasShortcutKey="false" --> - <default> - <Key - latin:keyLabel="@string/keylabel_for_f1" - latin:keyWidth="9.2%p" - latin:keyStyle="f1PopupStyle" /> - </default> - </switch> - </default> - </switch> -</merge> diff --git a/java/res/xml/kbd_symbols_row4.xml b/java/res/xml/kbd_symbols_row4.xml deleted file mode 100644 index 864cf2b8e..000000000 --- a/java/res/xml/kbd_symbols_row4.xml +++ /dev/null @@ -1,67 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="10%p" - > - <switch> - <case - latin:hasSettingsKey="false" - latin:navigateAction="false" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="15%p" /> - <include - latin:keyboardLayout="@xml/kbd_symbols_f1" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="50%p" /> - <Key - latin:keyStyle="punctuationKeyStyle" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </case> - <!-- hasSettingsKey="true" or navigateAction="true" --> - <default> - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="13.75%p" /> - <include - latin:keyboardLayout="@xml/kbd_settings_or_tab" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_f1" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="35.83%p" /> - <Key - latin:keyStyle="punctuationKeyStyle" - latin:keyWidth="9.2%p" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </default> - </switch> - </Row> -</merge> diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml index 9c163d694..41a5571ef 100644 --- a/java/res/xml/kbd_symbols_shift.xml +++ b/java/res/xml/kbd_symbols_shift.xml @@ -22,5 +22,5 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:keyboardLayout="@xml/kbd_rows_symbols_shift" /> + latin:keyboardLayout="@xml/rows_symbols_shift" /> </Keyboard> diff --git a/java/res/xml/kbd_symbols_shift_row4.xml b/java/res/xml/kbd_symbols_shift_row4.xml deleted file mode 100644 index 89e80e5f7..000000000 --- a/java/res/xml/kbd_symbols_shift_row4.xml +++ /dev/null @@ -1,78 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2010, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<merge - xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" -> - <Row - latin:keyWidth="10%p" - > - <switch> - <case - latin:hasSettingsKey="false" - latin:navigateAction="false" - > - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="15%p" /> - <!-- Note: Neither DroidSans nor Roboto have a glyph for ‟ Double high-reversed-9 quotation mark U+201F. --> - <!-- latin:keyLabelOption="hasPopupHint" --> - <!-- latin:moreKeys="‟" --> - <Key - latin:keyLabel="„" - latin:backgroundType="functional" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="50%p" /> - <Key - latin:keyLabel="…" - latin:backgroundType="functional" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </case> - <!-- hasSettingsKey="true" or navigateAction="true" --> - <default> - <Key - latin:keyStyle="toAlphaKeyStyle" - latin:keyWidth="13.75%p" /> - <include - latin:keyboardLayout="@xml/kbd_settings_or_tab" /> - <!-- Note: Neither DroidSans nor Roboto have a glyph for ‟ Double high-reversed-9 quotation mark U+201F. --> - <!-- latin:keyLabelOption="hasPopupHint" --> - <!-- latin:moreKeys="‟" --> - <Key - latin:keyLabel="„" - latin:keyWidth="9.2%p" - latin:backgroundType="functional" /> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="35.83%p" /> - <Key - latin:keyLabel="…" - latin:keyWidth="9.2%p" - latin:backgroundType="functional" /> - <Key - latin:keyStyle="returnKeyStyle" - latin:keyWidth="fillRight" /> - </default> - </switch> - </Row> -</merge> diff --git a/java/res/xml/kbd_settings_or_tab.xml b/java/res/xml/key_azerty_quote.xml index 4a8bcc7a6..e1d180443 100644 --- a/java/res/xml/kbd_settings_or_tab.xml +++ b/java/res/xml/key_azerty_quote.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -23,23 +23,15 @@ > <switch> <case - latin:hasSettingsKey="true" + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" > <Key - latin:keyStyle="settingsKeyStyle" - latin:keyWidth="9.2%p" /> + latin:keyLabel=":" /> </case> - <!-- hasSettingsKey="false" --> - <case - latin:navigateAction="true" - > - <Key - latin:keyStyle="tabKeyStyle" - latin:keyWidth="9.2%p" /> - </case> - <!-- hasSettingsKey="false" and navigateAction="false" --> <default> - <!-- No key. --> + <Key + latin:keyLabel="\'" + latin:moreKeys="\@string/more_keys_for_single_quote" /> </default> </switch> </merge> diff --git a/java/res/xml-sw768dp/kbd_row3_comma_period.xml b/java/res/xml/key_greek_semicolon.xml index b84443078..a28b772fd 100644 --- a/java/res/xml-sw768dp/kbd_row3_comma_period.xml +++ b/java/res/xml/key_greek_semicolon.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -23,24 +23,20 @@ > <switch> <case - latin:mode="email" + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" > <Key - latin:keyLabel="," /> - <Key - latin:keyLabel="." /> + latin:keyLabel=":" + latin:keyHintLabel="1" + latin:moreKeys=";" + latin:additionalMoreKeys="1" /> </case> <default> <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> - <Key - latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> + latin:keyLabel=";" + latin:keyHintLabel="1" + latin:moreKeys=":" + latin:additionalMoreKeys="1" /> </default> </switch> </merge> diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/key_styles_common.xml index 453b05dff..087b8952f 100644 --- a/java/res/xml/kbd_key_styles.xml +++ b/java/res/xml/key_styles_common.xml @@ -27,139 +27,110 @@ latin:clobberSettingsKey="true" > <key-style - latin:styleName="f1PopupStyle" - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_f1" + latin:styleName="f1MoreKeysStyle" latin:backgroundType="functional" /> </case> - <!-- clobberSettingsKey="false --> + <!-- clobberSettingsKey="false" --> + <default> + <key-style + latin:styleName="f1MoreKeysStyle" + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="@string/settings_as_more_key" + latin:backgroundType="functional" /> + </default> + </switch> + <!-- Functional key styles --> + <switch> <case - latin:hasSettingsKey="false" + latin:keyboardSetElement="alphabetManualShifted|alphabetAutomaticShifted" > <key-style - latin:styleName="f1PopupStyle" - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_f1_settings" - latin:backgroundType="functional" /> + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> </case> - <!-- clobberSettingsKey="false" hasSettingsKey="true" --> <case - latin:navigateAction="true" + latin:keyboardSetElement="alphabetShiftLocked|alphabetShiftLockShifted" > <key-style - latin:styleName="f1PopupStyle" - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_f1_navigate" - latin:backgroundType="functional" /> + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKeyShifted" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOn" /> </case> - <!-- clobberSettingsKey="false" and hasSettingsKey="true" navigateAction="false" --> <default> <key-style - latin:styleName="f1PopupStyle" - latin:keyLabelOption="hasPopupHint" - latin:moreKeys="@string/more_keys_for_f1" - latin:backgroundType="functional" /> + latin:styleName="shiftKeyStyle" + latin:code="@integer/key_shift" + latin:keyIcon="iconShiftKey" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="stickyOff" /> </default> </switch> - <!-- Functional key styles --> - <key-style - latin:styleName="shiftKeyStyle" - latin:code="@integer/key_shift" - latin:keyIcon="iconShiftKey" - latin:keyIconShifted="iconShiftedShiftKey" - latin:backgroundType="sticky" /> <key-style latin:styleName="deleteKeyStyle" latin:code="@integer/key_delete" latin:keyIcon="iconDeleteKey" - latin:backgroundType="functional" - latin:isRepeatable="true" /> - <!-- Return key style --> + latin:keyActionFlags="isRepeatable|noKeyPreview" + latin:backgroundType="functional" /> + <include + latin:keyboardLayout="@xml/key_styles_enter" /> <switch> + <!-- Shift + Enter in textMultiLine field. --> + <case + latin:isMultiLine="true" + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <key-style + latin:styleName="enterKeyStyle" + latin:parentStyle="defaultEnterKeyStyle" /> + </case> + <!-- Smiley in textShortMessage field. + Overrides common enter key style. --> <case latin:mode="im" > - <!-- Smiley key. --> <key-style - latin:styleName="returnKeyStyle" + latin:styleName="enterKeyStyle" latin:keyLabel=":-)" latin:keyOutputText=":-) " - latin:keyLabelOption="hasPopupHint" + latin:keyLabelFlags="hasPopupHint" latin:moreKeys="@string/more_keys_for_smiley" - latin:maxMoreKeysColumn="5" latin:backgroundType="functional" /> </case> - <case - latin:imeAction="actionGo" - > - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyLabel="@string/label_go_key" - latin:keyLabelOption="autoXScale" - latin:backgroundType="action" /> - </case> - <case - latin:imeAction="actionNext" - > - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyLabel="@string/label_next_key" - latin:keyLabelOption="autoXScale" - latin:backgroundType="action" /> - </case> - <case - latin:imeAction="actionDone" - > - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyLabel="@string/label_done_key" - latin:keyLabelOption="autoXScale" - latin:backgroundType="action" /> - </case> - <case - latin:imeAction="actionSend" - > - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyLabel="@string/label_send_key" - latin:keyLabelOption="autoXScale" - latin:backgroundType="action" /> - </case> - <case - latin:imeAction="actionSearch" - > - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyIcon="iconSearchKey" - latin:backgroundType="action" /> - </case> - <default> - <key-style - latin:styleName="returnKeyStyle" - latin:code="@integer/key_return" - latin:keyIcon="iconReturnKey" - latin:backgroundType="functional" /> - </default> </switch> <key-style latin:styleName="spaceKeyStyle" latin:code="@integer/key_space" + latin:keyActionFlags="noKeyPreview|enableLongPress" + latin:backgroundType="functional" /> + <key-style + latin:styleName="zwnjKeyStyle" + latin:keyLabel="‌" + latin:moreKeys="‍" + latin:keyLabelFlags="hasPopupHint" latin:backgroundType="functional" /> <key-style latin:styleName="shortcutKeyStyle" latin:code="@integer/key_shortcut" latin:keyIcon="iconShortcutKey" - latin:parentStyle="f1PopupStyle" /> + latin:keyIconDisabled="iconDisabledShortcutKey" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:altCode="@integer/key_space" + latin:parentStyle="f1MoreKeysStyle" /> <key-style - latin:styleName="settingsKeyStyle" - latin:code="@integer/key_settings" - latin:keyIcon="iconSettingsKey" + latin:styleName="languageSwitchKeyStyle" + latin:code="@integer/key_language_switch" + latin:keyIcon="iconLanguageSwitchKey" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress" + latin:altCode="@integer/key_space" latin:backgroundType="functional" /> + <!-- U+200C: "" ZERO WIDTH NON-JOINER + U+200D: "" ZERO WIDTH JOINER --> <key-style latin:styleName="tabKeyStyle" latin:code="@integer/key_tab" @@ -186,7 +157,8 @@ latin:code="@integer/key_switch_alpha_symbol" latin:keyIcon="iconShortcutForLabel" latin:keyLabel="@string/label_to_symbol_with_microphone_key" - latin:keyLabelOption="withIconRight" + latin:keyLabelFlags="withIconRight|preserveCase" + latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> </case> <default> @@ -194,6 +166,8 @@ latin:styleName="toSymbolKeyStyle" latin:code="@integer/key_switch_alpha_symbol" latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> </default> </switch> @@ -201,23 +175,28 @@ latin:styleName="toAlphaKeyStyle" latin:code="@integer/key_switch_alpha_symbol" latin:keyLabel="@string/label_to_alpha_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> <key-style latin:styleName="toMoreSymbolKeyStyle" latin:code="@integer/key_shift" latin:keyLabel="@string/label_to_more_symbol_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> <key-style latin:styleName="backFromMoreSymbolKeyStyle" latin:code="@integer/key_shift" latin:keyLabel="@string/label_to_symbol_key" + latin:keyLabelFlags="preserveCase" + latin:keyActionFlags="noKeyPreview" latin:backgroundType="functional" /> <key-style latin:styleName="punctuationKeyStyle" latin:keyLabel="." latin:keyHintLabel="@string/keyhintlabel_for_punctuation" - latin:keyLabelOption="hasPopupHint" + latin:keyLabelFlags="hasPopupHint|preserveCase" latin:moreKeys="@string/more_keys_for_punctuation" - latin:maxMoreKeysColumn="@integer/mini_keyboard_column_for_punctuation" latin:backgroundType="functional" /> </merge> diff --git a/java/res/xml/kbd_currency_key_styles.xml b/java/res/xml/key_styles_currency.xml index 225888337..3e4afdfb5 100644 --- a/java/res/xml/kbd_currency_key_styles.xml +++ b/java/res/xml/key_styles_currency.xml @@ -26,7 +26,7 @@ latin:passwordInput="true" > <include - latin:keyboardLayout="@xml/kbd_currency_dollar_key_styles" /> + latin:keyboardLayout="@xml/key_styles_currency_dollar" /> </case> <!-- Countries using Euro currency, 23 countries as for January 2011. --> 1. Andorra (ca_AD, ca_ES) @@ -62,19 +62,19 @@ latin:localeCode="da|de|es|el|fi|fr|it|nl|sk|sl|pt_PT|tr" > <include - latin:keyboardLayout="@xml/kbd_currency_euro_key_styles" /> + latin:keyboardLayout="@xml/key_styles_currency_euro" /> </case> <case latin:languageCode="ca|et|lb|mt|sla" > <include - latin:keyboardLayout="@xml/kbd_currency_euro_key_styles" /> + latin:keyboardLayout="@xml/key_styles_currency_euro" /> </case> <case latin:countryCode="AD|AT|BE|CY|EE|FI|FR|DE|GR|IE|IT|XK|LU|MT|MO|ME|NL|PT|SM|SK|SI|ES|VA" > <include - latin:keyboardLayout="@xml/kbd_currency_euro_key_styles" /> + latin:keyboardLayout="@xml/key_styles_currency_euro" /> </case> <case latin:languageCode="iw" @@ -121,7 +121,7 @@ </case> <default> <include - latin:keyboardLayout="@xml/kbd_currency_dollar_key_styles" /> + latin:keyboardLayout="@xml/key_styles_currency_dollar" /> </default> </switch> </merge> diff --git a/java/res/xml/kbd_currency_dollar_key_styles.xml b/java/res/xml/key_styles_currency_dollar.xml index d5dca2afa..d5dca2afa 100644 --- a/java/res/xml/kbd_currency_dollar_key_styles.xml +++ b/java/res/xml/key_styles_currency_dollar.xml diff --git a/java/res/xml/kbd_currency_euro_key_styles.xml b/java/res/xml/key_styles_currency_euro.xml index 6edddf074..6edddf074 100644 --- a/java/res/xml/kbd_currency_euro_key_styles.xml +++ b/java/res/xml/key_styles_currency_euro.xml diff --git a/java/res/xml/key_styles_enter.xml b/java/res/xml/key_styles_enter.xml new file mode 100644 index 000000000..a4c9a3396 --- /dev/null +++ b/java/res/xml/key_styles_enter.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- Navigate more keys style --> + <switch> + <case + latin:imeAction="actionNext" + latin:navigatePrevious="true" + > + <key-style + latin:styleName="navigateMoreKeysStyle" + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/action_previous_as_more_key" /> + </case> + <case + latin:imeAction="actionNext" + latin:navigatePrevious="false" + > + <key-style + latin:styleName="navigateMoreKeysStyle" /> + </case> + <case + latin:imeAction="actionPrevious" + latin:navigateNext="true" + > + <key-style + latin:styleName="navigateMoreKeysStyle" + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/action_next_as_more_key" /> + </case> + <case + latin:imeAction="actionPrevious" + latin:navigateNext="false" + > + <key-style + latin:styleName="navigateMoreKeysStyle" /> + </case> + <!-- imeAction!="actionNext" and imeAction!="actionPrevious" --> + <case + latin:navigateNext="true" + latin:navigatePrevious="true" + > + <key-style + latin:styleName="navigateMoreKeysStyle" + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="!fixedColumnOrder!2,!needsDividers!,@string/action_previous_as_more_key,@string/action_next_as_more_key" /> + </case> + <case + latin:navigateNext="true" + latin:navigatePrevious="false" + > + <key-style + latin:styleName="navigateMoreKeysStyle" + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/action_next_as_more_key" /> + </case> + <case + latin:navigateNext="false" + latin:navigatePrevious="true" + > + <key-style + latin:styleName="navigateMoreKeysStyle" + latin:keyLabelFlags="hasPopupHint|preserveCase" + latin:moreKeys="@string/action_previous_as_more_key" /> + </case> + <!-- naviagteNext="false" and navigatePrevious="false" --> + <default> + <key-style + latin:styleName="navigateMoreKeysStyle" /> + </default> + </switch> + <!-- Enter key style --> + <key-style + latin:styleName="defaultEnterKeyStyle" + latin:code="@integer/key_enter" + latin:keyIcon="iconReturnKey" + latin:keyLabelFlags="autoXScale|preserveCase" + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" + latin:parentStyle="navigateMoreKeysStyle" /> + <key-style + latin:styleName="defaultActionKeyStyle" + latin:code="@integer/key_action_enter" + latin:keyIcon="iconUndefined" + latin:backgroundType="action" + latin:parentStyle="defaultEnterKeyStyle" /> + <switch> + <!-- Shift + Enter in textMultiLine field. --> + <case + latin:isMultiLine="true" + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <key-style + latin:styleName="enterKeyStyle" + latin:parentStyle="defaultEnterKeyStyle" /> + </case> + <case + latin:imeAction="actionGo" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabel="@string/label_go_key" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionNext" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabel="@string/label_next_key" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionPrevious" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabel="@string/label_previous_key" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionDone" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabel="@string/label_done_key" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionSend" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabel="@string/label_send_key" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionSearch" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyIcon="iconSearchKey" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <case + latin:imeAction="actionCustomLabel" + > + <key-style + latin:styleName="enterKeyStyle" + latin:keyLabelFlags="fromCustomActionLabel" + latin:parentStyle="defaultActionKeyStyle" /> + </case> + <!-- imeAction is either actionNone or actionUnspecified. --> + <default> + <key-style + latin:styleName="enterKeyStyle" + latin:parentStyle="defaultEnterKeyStyle" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/kbd_numkey_styles.xml b/java/res/xml/key_styles_number.xml index 5d5439906..1fc21694d 100644 --- a/java/res/xml/kbd_numkey_styles.xml +++ b/java/res/xml/key_styles_number.xml @@ -22,23 +22,28 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <key-style + latin:styleName="numKeyBaseStyle" + latin:keyActionFlags="noKeyPreview" /> + <key-style latin:styleName="numKeyStyle" - latin:keyLabelOption="largeLetter|followKeyLetterRatio" /> + latin:keyLabelFlags="largeLetter|followKeyLetterRatio" + latin:parentStyle="numKeyBaseStyle" /> <key-style latin:styleName="numModeKeyStyle" - latin:keyLabelOption="fontNormal|followKeyLetterRatio" /> + latin:keyLabelFlags="fontNormal|followKeyLetterRatio" + latin:parentStyle="numKeyBaseStyle" /> <key-style latin:styleName="numFunctionalKeyStyle" - latin:keyLabelOption="largeLetter|followKeyLetterRatio" - latin:backgroundType="functional" /> + latin:keyLabelFlags="largeLetter|followKeyLetterRatio" + latin:backgroundType="functional" + latin:parentStyle="numKeyBaseStyle" /> <key-style latin:styleName="numberKeyStyle" - latin:keyLabelOption="alignLeftOfCenter|hasHintLabel" + latin:keyLabelFlags="alignLeftOfCenter|hasHintLabel" latin:parentStyle="numKeyStyle" /> <key-style latin:styleName="num0KeyStyle" - latin:code="48" - latin:keyLabel="0 +" + latin:keyLabel="0" latin:parentStyle="numberKeyStyle" /> <key-style latin:styleName="num1KeyStyle" @@ -84,23 +89,46 @@ latin:keyLabel="9" latin:keyHintLabel="WXYZ" latin:parentStyle="numberKeyStyle" /> + <!-- U+002A: "*" ASTERISK + U+FF0A: "*" FULLWIDTH ASTERISK --> <key-style latin:styleName="numStarKeyStyle" - latin:code="42" - latin:keyLabel="\uff0a" + latin:code="0x002A" + latin:keyLabel="*" latin:parentStyle="numKeyStyle" /> + <!-- Only for non-tablet device --> <key-style - latin:styleName="numSwitchToAltKeyStyle" - latin:code="@integer/key_shift" + latin:styleName="numPhoneToSymbolKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" latin:keyLabel="@string/label_to_phone_symbols_key" latin:parentStyle="numModeKeyStyle" /> <key-style - latin:styleName="numSwitchToNumericKeyStyle" - latin:code="@integer/key_shift" + latin:styleName="numPhoneToNumericKeyStyle" + latin:code="@integer/key_switch_alpha_symbol" latin:keyLabel="@string/label_to_phone_numeric_key" latin:parentStyle="numModeKeyStyle" /> + <!-- U+002C: "," COMMA --> + <key-style + latin:styleName="numPauseKeyStyle" + latin:code="0x002C" + latin:keyLabel="@string/label_pause_key" + latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale" + latin:parentStyle="numKeyBaseStyle" /> + <!-- U+003B: ";" SEMICOLON --> + <key-style + latin:styleName="numWaitKeyStyle" + latin:code="0x003B" + latin:keyLabel="@string/label_wait_key" + latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale" + latin:parentStyle="numKeyBaseStyle" /> + <key-style + latin:styleName="numTabKeyStyle" + latin:keyActionFlags="noKeyPreview" + latin:parentStyle="tabKeyStyle" /> <key-style latin:styleName="numSpaceKeyStyle" latin:code="@integer/key_space" - latin:keyIcon="iconSpaceKey" /> + latin:keyIcon="iconSpaceKeyForNumberLayout" + latin:keyActionFlags="enableLongPress" + latin:parentStyle="numKeyBaseStyle" /> </merge> diff --git a/java/res/xml/keyboard_set.xml b/java/res/xml/keyboard_set.xml new file mode 100644 index 000000000..1398b137c --- /dev/null +++ b/java/res/xml/keyboard_set.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyboardLocale="en_GB,en_US"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_symbols_shift" /> + <Element + latin:elementName="phone" + latin:elementKeyboard="@xml/kbd_phone" /> + <Element + latin:elementName="phoneSymbols" + latin:elementKeyboard="@xml/kbd_phone_symbols" /> + <Element + latin:elementName="number" + latin:elementKeyboard="@xml/kbd_number" /> +</KeyboardSet> diff --git a/java/res/xml-sw600dp/kbd_row3_comma_period.xml b/java/res/xml/keys_comma_period.xml index b84443078..6db02b61d 100644 --- a/java/res/xml-sw600dp/kbd_row3_comma_period.xml +++ b/java/res/xml/keys_comma_period.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -33,14 +33,14 @@ <default> <Key latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="!" - latin:moreKeys="!" /> + latin:moreKeys="!" + latin:keyStyle="hasShiftedLetterHintStyle" /> <Key latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" latin:keyHintLabel="\?" - latin:moreKeys="\?" /> + latin:moreKeys="\?" + latin:keyStyle="hasShiftedLetterHintStyle" /> </default> </switch> </merge> diff --git a/java/res/xml/keys_curly_brackets.xml b/java/res/xml/keys_curly_brackets.xml new file mode 100644 index 000000000..d21a09281 --- /dev/null +++ b/java/res/xml/keys_curly_brackets.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="{" + latin:code="@integer/keycode_for_left_curly_bracket" /> + <Key + latin:keyLabel="}" + latin:code="@integer/keycode_for_right_curly_bracket" /> +</merge> diff --git a/java/res/xml/keys_less_greater.xml b/java/res/xml/keys_less_greater.xml new file mode 100644 index 000000000..8961d9ce6 --- /dev/null +++ b/java/res/xml/keys_less_greater.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="<" + latin:code="@integer/keycode_for_less_than" + latin:moreKeys="@string/more_keys_for_less_than" /> + <Key + latin:keyLabel=">" + latin:code="@integer/keycode_for_greater_than" + latin:moreKeys="@string/more_keys_for_greater_than" /> +</merge> diff --git a/java/res/xml-sw768dp/kbd_rows_qwerty.xml b/java/res/xml/keys_parentheses.xml index 6237712f6..6853bf167 100644 --- a/java/res/xml-sw768dp/kbd_rows_qwerty.xml +++ b/java/res/xml/keys_parentheses.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2010, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -21,14 +21,12 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > - <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> + <Key + latin:keyLabel="(" + latin:code="@integer/keycode_for_left_parenthesis" + latin:moreKeys="@string/more_keys_for_left_parenthesis" /> + <Key + latin:keyLabel=")" + latin:code="@integer/keycode_for_right_parenthesis" + latin:moreKeys="@string/more_keys_for_right_parenthesis" /> </merge> diff --git a/java/res/xml/keys_square_brackets.xml b/java/res/xml/keys_square_brackets.xml new file mode 100644 index 000000000..44387c3bf --- /dev/null +++ b/java/res/xml/keys_square_brackets.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="[" + latin:code="@integer/keycode_for_left_square_bracket" /> + <Key + latin:keyLabel="]" + latin:code="@integer/keycode_for_right_square_bracket" /> +</merge> diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index 6184add4d..cdcea0ed0 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -20,7 +20,47 @@ <!-- The attributes in this XML file provide configuration information --> <!-- for the Input Method Manager. --> -<!-- Keyboard: en_US, en_GB, ar, cs, da, de, de(QWERTY), es, es_US, fi, fr, fr_CA, fr_CH, hr, hu, it, iw, nb, nl, pl, pt, ru, sr, sv, tr --> +<!-- Supported locales: name/layout + ar: Arabic/arabic + be: Belarusian/east_slavic + bg: Bulgarian/bulgarian + cs: Czech/qwertz + da: Danish/nordic + de: German/qwertz + de_ZZ: German (QWERTY)/qwerty + el: Greek/greek + en_US: English United States/qwerty + en_GB: English Great Britain/qwerty + es: Spanish/spanish + et: Estonian/nordic + fa: Persian/arabic + fi: Finnish/nordic + fr: French/azerty + fr_CA: French Canada/qwerty + fr_CH: French Switzerland/qwertz + hr: Croatian/qwertz + hu: Hungarian/qwertz + it: Italian/qwerty + iw: Hebrew/hebrew + ka: Georgian/georgian + ky: Kyrgyz/east_slavic + lt: Lithuanian/qwerty + lv: Latvian/qwerty + mk: Macedonian/south_slavic + nb: Norwaian Bokmål/nordic + nl: Dutch/qwerty + pl: Polish/qwerty + pt: Portuguese/qwerty + ro: Romanian/qwerty + ru: Russian/east_slavic + sk: Slovak/qwerty + sl: Slovenian/qwerty + sr: Serbian/south_slavic + sv: Swedish/nordic + tr: Turkish/qwerty + uk: Ukrainian/east_slavic + vi: Vietnamese/qwerty + --> <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. --> <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default subtype.--> @@ -31,7 +71,7 @@ android:label="@string/subtype_en_US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection,EnabledWhenDefaultIsNotAsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_en_GB" @@ -47,6 +87,18 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="be" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="bg" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="cs" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" @@ -64,19 +116,37 @@ android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" - android:label="@string/subtype_de_qwerty" + android:label="@string/subtype_generic_qwerty" android:imeSubtypeLocale="de" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_ZZ,SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="el" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="es" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="et" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="fa" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="fi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" @@ -126,6 +196,36 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="ka" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="ky" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="lt" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="lv" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="mk" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="nb" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" @@ -150,12 +250,30 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="ro" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="ru" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" + android:imeSubtypeLocale="sk" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="sl" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="SupportTouchPositionCorrection" @@ -172,4 +290,16 @@ android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="uk" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="vi" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + /> </input-method> diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index dcaa2029c..ebca25089 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -44,11 +44,6 @@ android:title="@string/popup_on_keypress" android:persistent="true" android:defaultValue="@bool/config_default_popup_preview" /> - <CheckBoxPreference - android:key="show_settings_key" - android:title="@string/prefs_settings_key" - android:persistent="true" - android:defaultValue="@bool/config_default_show_settings_key" /> <ListPreference android:key="voice_mode" android:title="@string/voice_input" @@ -97,6 +92,17 @@ android:key="pref_advanced_settings" android:title="@string/advanced_settings" android:summary="@string/advanced_settings_summary"> + <CheckBoxPreference + android:key="pref_suppress_language_switch_key" + android:title="@string/suppress_language_switch_key" + android:persistent="true" + android:defaultValue="false" /> + <CheckBoxPreference + android:key="pref_include_other_imes_in_language_switch_list" + android:title="@string/include_other_imes_in_language_switch_list" + android:summary="@string/include_other_imes_in_language_switch_list_summary" + android:persistent="true" + android:defaultValue="false" /> <!-- Values for popup dismiss delay are added programatically --> <ListPreference android:key="pref_key_preview_popup_dismiss_delay" @@ -114,6 +120,13 @@ android:persistent="true" android:defaultValue="true" /> <CheckBoxPreference + android:key="bigram_prediction" + android:dependency="bigram_suggestion" + android:title="@string/bigram_prediction" + android:summary="@string/bigram_prediction_summary" + android:persistent="true" + android:defaultValue="false" /> + <CheckBoxPreference android:key="enable_span_insert" android:title="@string/enable_span_insert" android:summary="@string/enable_span_insert_summary" @@ -125,15 +138,6 @@ <PreferenceScreen android:key="pref_keypress_sound_volume" android:title="@string/prefs_keypress_sound_volume_settings" /> - <!-- TODO: evaluate results and revive this option. The code - already supports it. --> - <!-- <CheckBoxPreference --> - <!-- android:key="bigram_prediction" --> - <!-- android:dependency="bigram_suggestion" --> - <!-- android:title="@string/bigram_prediction" --> - <!-- android:summary="@string/bigram_prediction_summary" --> - <!-- android:persistent="true" --> - <!-- android:defaultValue="false" /> --> </PreferenceScreen> </PreferenceCategory> </PreferenceScreen> diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index 80613a56f..b926ed065 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -32,7 +32,7 @@ android:persistent="true" android:entryValues="@array/keyboard_layout_modes_values" android:entries="@array/keyboard_layout_modes" - android:defaultValue="@string/config_default_keyboard_theme_id" + android:defaultValue="@string/config_default_keyboard_theme_index" /> <CheckBoxPreference @@ -42,4 +42,10 @@ android:defaultValue="false" /> + <CheckBoxPreference + android:key="force_non_distinct_multitouch" + android:title="@string/prefs_force_non_distinct_multitouch" + android:persistent="true" + android:defaultValue="false" + /> </PreferenceScreen> diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml new file mode 100644 index 000000000..b2b47e9b5 --- /dev/null +++ b/java/res/xml/row_qwerty4.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyWidth="15%p" /> + <switch> + <case + latin:mode="url" + > + <Key + latin:keyLabel="/" + latin:keyStyle="f1MoreKeysStyle" /> + </case> + <case + latin:mode="email" + > + <Key + latin:keyLabel="\@" + latin:keyStyle="f1MoreKeysStyle" /> + </case> + <case + latin:hasShortcutKey="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" /> + </case> + <!-- latin:hasShortcutKey="false" --> + <default> + <Key + latin:keyLabel="@string/keylabel_for_comma" + latin:keyLabelFlags="hasPopupHint" + latin:additionalMoreKeys="@string/more_keys_for_comma" + latin:keyStyle="f1MoreKeysStyle" /> + </default> + </switch> + <switch> + <case + latin:languageCode="fa" + latin:languageSwitchKeyEnabled="true" + > + <Key + latin:keyStyle="languageSwitchKeyStyle" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <case + latin:languageCode="fa" + latin:languageSwitchKeyEnabled="false" + > + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + <Key + latin:keyStyle="zwnjKeyStyle" /> + </case> + <case + latin:languageSwitchKeyEnabled="true" + > + <Key + latin:keyStyle="languageSwitchKeyStyle" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + </case> + <!-- languageSwitchKeyEnabled="false" --> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="50%p" /> + </default> + </switch> + <Key + latin:keyStyle="punctuationKeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillRight" /> + </Row> +</merge> diff --git a/java/res/xml/rowkeys_arabic1.xml b/java/res/xml/rowkeys_arabic1.xml new file mode 100644 index 000000000..b1bf790e4 --- /dev/null +++ b/java/res/xml/rowkeys_arabic1.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0636: "ض" ARABIC LETTER DAD + U+0661: "١" ARABIC-INDIC DIGIT ONE --> + <Key + latin:keyLabel="ض" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1,١" /> + <!-- U+0635: "ص" ARABIC LETTER SAD + U+0662: "٢" ARABIC-INDIC DIGIT TWO --> + <Key + latin:keyLabel="ص" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2,٢" /> + <!-- U+0642: "ق" ARABIC LETTER QAF + U+06A8: "ڨ" ARABIC LETTER QAF WITH THREE DOTS ABOVE + U+0663: "٣" ARABIC-INDIC DIGIT THREE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A8 ARABIC LETTER QAF WITH THREE DOTS ABOVE --> + <Key + latin:keyLabel="ق" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3,٣" + latin:moreKeys="ڨ" /> + <!-- U+0641: "ف" ARABIC LETTER FEH + U+06A4: "ڤ" ARABIC LETTER VEH + U+06A2: "ڢ" ARABIC LETTER FEH WITH DOT MOVED BELOW + U+06A5: "ڥ" ARABIC LETTER FEH WITH THREE DOTS BELOW + U+0664: "٤" ARABIC-INDIC DIGIT FOUR --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A2 ARABIC LETTER FEH WITH DOT MOVED BELOW --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06A5 ARABIC LETTER FEH WITH THREE DOTS BELOW --> + <Key + latin:keyLabel="ف" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4,٤" + latin:moreKeys="ڤ,ڢ,ڥ" /> + <!-- U+063A: "غ" ARABIC LETTER GHAIN + U+0665: "٥" ARABIC-INDIC DIGIT FIVE --> + <Key + latin:keyLabel="غ" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5,٥" /> + <!-- U+0639: "ع" ARABIC LETTER AIN + U+0666: "٦" ARABIC-INDIC DIGIT SIX --> + <Key + latin:keyLabel="ع" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6,٦" /> + <!-- U+0647: "ه" ARABIC LETTER HEH + U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM + U+0647 U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER + U+0667: "٧" ARABIC-INDIC DIGIT SEVEN --> + <Key + latin:keyLabel="ه" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7,٧" + latin:moreKeys="ﻫ|ه‍" /> + <!-- U+062E: "خ" ARABIC LETTER KHAH + U+0668: "٨" ARABIC-INDIC DIGIT EIGHT --> + <Key + latin:keyLabel="خ" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8,٨" /> + <!-- U+062D: "ح" ARABIC LETTER HAH + U+0669: "٩" ARABIC-INDIC DIGIT NINE --> + <Key + latin:keyLabel="ح" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9,٩" /> + <!-- U+062C: "ج" ARABIC LETTER JEEM + U+0686: "چ" ARABIC LETTER TCHEH + U+0660: "٠" ARABIC-INDIC DIGIT ZERO --> + <Key + latin:keyLabel="ج" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0,٠" + latin:moreKeys="چ" /> +</merge> diff --git a/java/res/xml/rowkeys_arabic2.xml b/java/res/xml/rowkeys_arabic2.xml new file mode 100644 index 000000000..f86aae014 --- /dev/null +++ b/java/res/xml/rowkeys_arabic2.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0634: "ش" ARABIC LETTER SHEEN + U+069C: "ڜ" ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+069C ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE --> + <Key + latin:keyLabel="ش" + latin:moreKeys="ڜ" /> + <!-- U+0633: "س" ARABIC LETTER SEEN --> + <Key + latin:keyLabel="س" /> + <!-- U+064A: "ي" ARABIC LETTER YEH + U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE + U+0649: "ى" ARABIC LETTER ALEF MAKSURA --> + <Key + latin:keyLabel="ي" + latin:moreKeys="ئ,ى" /> + <!-- U+0628: "ب" ARABIC LETTER BEH + U+067E: "پ" ARABIC LETTER PEH --> + <Key + latin:keyLabel="ب" + latin:moreKeys="پ" /> + <!-- U+0644: "ل" ARABIC LETTER LAM + U+FEFB: "ﻻ" ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + U+0627: "ا" ARABIC LETTER ALEF + U+FEF7: "ﻷ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE + U+FEF9: "ﻹ" ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM + U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW + U+FEF5: "ﻵ" ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE --> + <Key + latin:keyLabel="ل" + latin:moreKeys="ﻻ|لا,ﻷ|لأ,ﻹ|لإ,ﻵ|لآ" /> + <!-- U+0627: "ا" ARABIC LETTER ALEF + U+0621: "ء" ARABIC LETTER HAMZA + U+0671: "ٱ" ARABIC LETTER ALEF WASLA + U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE + U+0625: "إ" ARABIC LETTER ALEF WITH HAMZA BELOW + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE --> + <Key + latin:keyLabel="ا" + latin:moreKeys="ء,ٱ,أ,إ,آ" /> + <!-- U+062A: "ت" ARABIC LETTER TEH + U+062B: "ﺙ" ARABIC LETTER THEH --> + <Key + latin:keyLabel="ت" + latin:moreKeys="ث" /> + <!-- U+0646: "ن" ARABIC LETTER NOON --> + <Key + latin:keyLabel="ن" /> + <!-- U+0645: "م" ARABIC LETTER MEEM --> + <Key + latin:keyLabel="م" /> + <!-- U+0643: "ك" ARABIC LETTER KAF + U+06AF: "گ" ARABIC LETTER GAF + U+06A9: "ک" ARABIC LETTER KEHEH --> + <Key + latin:keyLabel="ك" + latin:moreKeys="گ,ک" + latin:keyWidth="fillRight" /> +</merge> diff --git a/java/res/xml/rowkeys_arabic3.xml b/java/res/xml/rowkeys_arabic3.xml new file mode 100644 index 000000000..9e9eac0d9 --- /dev/null +++ b/java/res/xml/rowkeys_arabic3.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0638: "ظ" ARABIC LETTER ZAH --> + <Key + latin:keyLabel="ظ" /> + <!-- U+0637: "ط" ARABIC LETTER TAH --> + <Key + latin:keyLabel="ط" /> + <!-- U+0630: "ذ" ARABIC LETTER THAL --> + <Key + latin:keyLabel="ذ" /> + <!-- U+062F: "د" ARABIC LETTER DAL --> + <Key + latin:keyLabel="د" /> + <!-- U+0632: "ز" ARABIC LETTER ZAIN + U+0698: "ژ" ARABIC LETTER JEH --> + <Key + latin:keyLabel="ز" + latin:moreKeys="ژ" /> + <!-- U+0631: "ر" ARABIC LETTER REH --> + <Key + latin:keyLabel="ر" /> + <!-- U+0629: "ة" ARABIC LETTER TEH MARBUTA --> + <Key + latin:keyLabel="ة" /> + <!-- U+0648: "و" ARABIC LETTER WAW + U+0624: "ﺅ" ARABIC LETTER WAW WITH HAMZA ABOVE --> + <Key + latin:keyLabel="و" + latin:moreKeys="ؤ" /> +</merge> diff --git a/java/res/xml/rowkeys_azerty1.xml b/java/res/xml/rowkeys_azerty1.xml new file mode 100644 index 000000000..99834321f --- /dev/null +++ b/java/res/xml/rowkeys_azerty1.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="a" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" + latin:moreKeys="@string/more_keys_for_a" /> + <Key + latin:keyLabel="z" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" + latin:moreKeys="@string/more_keys_for_z" /> + <Key + latin:keyLabel="e" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="@string/more_keys_for_e" /> + <Key + latin:keyLabel="r" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" + latin:moreKeys="@string/more_keys_for_r" /> + <Key + latin:keyLabel="t" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" + latin:moreKeys="@string/more_keys_for_t" /> + <Key + latin:keyLabel="y" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" + latin:moreKeys="@string/more_keys_for_y" /> + <Key + latin:keyLabel="u" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" + latin:moreKeys="@string/more_keys_for_u" /> + <Key + latin:keyLabel="i" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="@string/more_keys_for_i" /> + <Key + latin:keyLabel="o" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" + latin:moreKeys="@string/more_keys_for_o" /> + <Key + latin:keyLabel="p" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> +</merge> diff --git a/java/res/xml/rowkeys_azerty2.xml b/java/res/xml/rowkeys_azerty2.xml new file mode 100644 index 000000000..11bcd67c7 --- /dev/null +++ b/java/res/xml/rowkeys_azerty2.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="q" /> + <Key + latin:keyLabel="s" + latin:moreKeys="@string/more_keys_for_s" /> + <Key + latin:keyLabel="d" + latin:moreKeys="@string/more_keys_for_d" /> + <Key + latin:keyLabel="f" /> + <Key + latin:keyLabel="g" + latin:moreKeys="@string/more_keys_for_g" /> + <Key + latin:keyLabel="h" /> + <Key + latin:keyLabel="j" /> + <Key + latin:keyLabel="k" + latin:moreKeys="@string/more_keys_for_k" /> + <Key + latin:keyLabel="l" + latin:moreKeys="@string/more_keys_for_l" /> + <Key + latin:keyLabel="m" /> +</merge> diff --git a/java/res/xml/kbd_rows_qwerty.xml b/java/res/xml/rowkeys_azerty3.xml index 6237712f6..1a0eaccdc 100644 --- a/java/res/xml/kbd_rows_qwerty.xml +++ b/java/res/xml/rowkeys_azerty3.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2010, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -21,14 +21,21 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <Key + latin:keyLabel="w" /> + <Key + latin:keyLabel="x" /> + <Key + latin:keyLabel="c" + latin:moreKeys="@string/more_keys_for_c" /> + <Key + latin:keyLabel="v" + latin:moreKeys="@string/more_keys_for_v" /> + <Key + latin:keyLabel="b" /> + <Key + latin:keyLabel="n" + latin:moreKeys="@string/more_keys_for_n" /> <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> + latin:keyboardLayout="@xml/key_azerty_quote" /> </merge> diff --git a/java/res/xml/rowkeys_bulgarian1.xml b/java/res/xml/rowkeys_bulgarian1.xml new file mode 100644 index 000000000..adeecaf20 --- /dev/null +++ b/java/res/xml/rowkeys_bulgarian1.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE --> + <Key + latin:keyLabel="ч" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA --> + <Key + latin:keyLabel="ш" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <!-- U+0435: "е" CYRILLIC SMALL LETTER IE --> + <Key + latin:keyLabel="е" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" /> + <!-- U+0440: "р" CYRILLIC SMALL LETTER ER --> + <Key + latin:keyLabel="р" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+0442: "т" CYRILLIC SMALL LETTER TE --> + <Key + latin:keyLabel="т" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" /> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <Key + latin:keyLabel="ъ" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" /> + <!-- U+0443: "у" CYRILLIC SMALL LETTER U --> + <Key + latin:keyLabel="у" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I + U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE --> + <Key + latin:keyLabel="и" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="ѝ" /> + <!-- U+043E: "о" CYRILLIC SMALL LETTER O --> + <Key + latin:keyLabel="о" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <!-- U+043F: "п" CYRILLIC SMALL LETTER PE --> + <Key + latin:keyLabel="п" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> + <!-- U+044F: "я" CYRILLIC SMALL LETTER YA --> + <Key + latin:keyLabel="я" /> +</merge> diff --git a/java/res/xml/rowkeys_bulgarian2.xml b/java/res/xml/rowkeys_bulgarian2.xml new file mode 100644 index 000000000..599edd3ed --- /dev/null +++ b/java/res/xml/rowkeys_bulgarian2.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0430: "а" CYRILLIC SMALL LETTER A --> + <Key + latin:keyLabel="а" /> + <!-- U+0441: "с" CYRILLIC SMALL LETTER ES --> + <Key + latin:keyLabel="с" /> + <!-- U+0434: "д" CYRILLIC SMALL LETTER DE --> + <Key + latin:keyLabel="д" /> + <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF --> + <Key + latin:keyLabel="ф" /> + <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE --> + <Key + latin:keyLabel="г" /> + <!-- U+0445: "х" CYRILLIC SMALL LETTER HA --> + <Key + latin:keyLabel="х" /> + <!-- U+0439: "й" CYRILLIC SMALL LETTER SHORT I --> + <Key + latin:keyLabel="й" /> + <!-- U+043A: "к" CYRILLIC SMALL LETTER KA --> + <Key + latin:keyLabel="к" /> + <!-- U+043B: "л" CYRILLIC SMALL LETTER EL --> + <Key + latin:keyLabel="л" /> + <!-- U+0449: "щ" CYRILLIC SMALL LETTER SHCHA --> + <Key + latin:keyLabel="щ" /> + <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN --> + <Key + latin:keyLabel="ь" /> +</merge> diff --git a/java/res/xml/rowkeys_bulgarian3.xml b/java/res/xml/rowkeys_bulgarian3.xml new file mode 100644 index 000000000..19872cdfe --- /dev/null +++ b/java/res/xml/rowkeys_bulgarian3.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <Key + latin:keyLabel="з" /> + <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE --> + <Key + latin:keyLabel="ж" /> + <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE --> + <Key + latin:keyLabel="ц" /> + <!-- U+0432: "в" CYRILLIC SMALL LETTER VE --> + <Key + latin:keyLabel="в" /> + <!-- U+0431: "б" CYRILLIC SMALL LETTER BE --> + <Key + latin:keyLabel="б" /> + <!-- U+043D: "н" CYRILLIC SMALL LETTER EN --> + <Key + latin:keyLabel="н" /> + <!-- U+043C: "м" CYRILLIC SMALL LETTER EM --> + <Key + latin:keyLabel="м" /> + <!-- U+044E: "ю" CYRILLIC SMALL LETTER YU --> + <Key + latin:keyLabel="ю" /> +</merge> diff --git a/java/res/xml/rowkeys_east_slavic1.xml b/java/res/xml/rowkeys_east_slavic1.xml new file mode 100644 index 000000000..ab83d99ce --- /dev/null +++ b/java/res/xml/rowkeys_east_slavic1.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0439: "й" CYRILLIC SMALL LETTER SHORT I --> + <Key + latin:keyLabel="й" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE --> + <Key + latin:keyLabel="ц" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <!-- U+0443: "у" CYRILLIC SMALL LETTER U --> + <Key + latin:keyLabel="у" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="@string/more_keys_for_cyrillic_u" /> + <!-- U+043A: "к" CYRILLIC SMALL LETTER KA --> + <Key + latin:keyLabel="к" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+0435: "е" CYRILLIC SMALL LETTER IE --> + <Key + latin:keyLabel="е" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" + latin:moreKeys="@string/more_keys_for_cyrillic_ye" /> + <!-- U+043D: "н" CYRILLIC SMALL LETTER EN --> + <Key + latin:keyLabel="н" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" + latin:moreKeys="@string/more_keys_for_cyrillic_en" /> + <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE --> + <Key + latin:keyLabel="г" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA --> + <Key + latin:keyLabel="ш" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_shcha" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <Key + latin:keyLabel="з" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> + <!-- U+0445: "х" CYRILLIC SMALL LETTER HA --> + <Key + latin:keyLabel="х" + latin:moreKeys="@string/more_keys_for_cyrillic_ha" /> +</merge> diff --git a/java/res/xml/rowkeys_east_slavic2.xml b/java/res/xml/rowkeys_east_slavic2.xml new file mode 100644 index 000000000..20415bc80 --- /dev/null +++ b/java/res/xml/rowkeys_east_slavic2.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF --> + <Key + latin:keyLabel="ф" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_yery" + latin:moreKeys="@string/more_keys_for_cyrillic_yery" /> + <!-- U+0432: "в" CYRILLIC SMALL LETTER VE --> + <Key + latin:keyLabel="в" /> + <!-- U+0430: "а" CYRILLIC SMALL LETTER A --> + <Key + latin:keyLabel="а" /> + <!-- U+043F: "п" CYRILLIC SMALL LETTER PE --> + <Key + latin:keyLabel="п" /> + <!-- U+0440: "р" CYRILLIC SMALL LETTER ER --> + <Key + latin:keyLabel="р" /> + <!-- U+043E: "о" CYRILLIC SMALL LETTER O --> + <Key + latin:keyLabel="о" + latin:moreKeys="@string/more_keys_for_cyrillic_o" /> + <!-- U+043B: "л" CYRILLIC SMALL LETTER EL --> + <Key + latin:keyLabel="л" /> + <!-- U+0434: "д" CYRILLIC SMALL LETTER DE --> + <Key + latin:keyLabel="д" /> + <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE --> + <Key + latin:keyLabel="ж" /> + <!-- U+044D: "э" CYRILLIC SMALL LETTER E --> + <Key + latin:keyLabel="э" /> +</merge> diff --git a/java/res/xml/rowkeys_east_slavic3.xml b/java/res/xml/rowkeys_east_slavic3.xml new file mode 100644 index 000000000..bb6722356 --- /dev/null +++ b/java/res/xml/rowkeys_east_slavic3.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+044F: "я" CYRILLIC SMALL LETTER YA --> + <Key + latin:keyLabel="я" /> + <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE --> + <Key + latin:keyLabel="ч" /> + <!-- U+0441: "с" CYRILLIC SMALL LETTER ES --> + <Key + latin:keyLabel="с" /> + <!-- U+043C: "м" CYRILLIC SMALL LETTER EM --> + <Key + latin:keyLabel="м" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_i" /> + <!-- U+0442: "т" CYRILLIC SMALL LETTER TE --> + <Key + latin:keyLabel="т" /> + <!-- U+044C: "ь" CYRILLIC SMALL LETTER SOFT SIGN --> + <Key + latin:keyLabel="ь" + latin:moreKeys="@string/more_keys_for_cyrillic_soft_sign" /> + <!-- U+0431: "б" CYRILLIC SMALL LETTER BE --> + <Key + latin:keyLabel="б" /> + <!-- U+044E: "ю" CYRILLIC SMALL LETTER YU --> + <Key + latin:keyLabel="ю" /> +</merge> diff --git a/java/res/xml/rowkeys_georgian1.xml b/java/res/xml/rowkeys_georgian1.xml new file mode 100644 index 000000000..b644cdfdd --- /dev/null +++ b/java/res/xml/rowkeys_georgian1.xml @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <Key + latin:keyLabel="Q" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <!-- U+10ED: "ჭ" GEORGIAN LETTER CHAR --> + <Key + latin:keyLabel="ჭ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <Key + latin:keyLabel="E" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" /> + <!-- U+10E6: "ღ" GEORGIAN LETTER GHAN --> + <Key + latin:keyLabel="ღ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+10D7: "თ" GEORGIAN LETTER TAN --> + <Key + latin:keyLabel="თ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" /> + <Key + latin:keyLabel="Y" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" /> + <Key + latin:keyLabel="U" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <Key + latin:keyLabel="I" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" /> + <Key + latin:keyLabel="O" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <Key + latin:keyLabel="P" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> + </case> + <default> + <!-- U+10E5: "ქ" GEORGIAN LETTER GHAN --> + <Key + latin:keyLabel="ქ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <!-- U+10EC: "წ" GEORGIAN LETTER CIL --> + <Key + latin:keyLabel="წ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <!-- U+10D4: "ე" GEORGIAN LETTER EN + U+10F1: "ჱ" GEORGIAN LETTER HE --> + <Key + latin:keyLabel="ე" + latin:moreKeys="ჱ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" /> + <!-- U+10E0: "რ" GEORGIAN LETTER RAE --> + <Key + latin:keyLabel="რ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+10E2: "ტ" GEORGIAN LETTER TAR --> + <Key + latin:keyLabel="ტ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" /> + <!-- U+10E7: "ყ" GEORGIAN LETTER QAR + U+10F8: "ჸ" GEORGIAN LETTER ELIFI --> + <Key + latin:keyLabel="ყ" + latin:moreKeys="ჸ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" /> + <!-- U+10E3: "უ" GEORGIAN LETTER UN --> + <Key + latin:keyLabel="უ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <!-- U+10D8: "ი" GEORGIAN LETTER IN + U+10F2: "ჲ" GEORGIAN LETTER HIE --> + <Key + latin:keyLabel="ი" + latin:moreKeys="ჲ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" /> + <!-- U+10DD: "ო" GEORGIAN LETTER ON --> + <Key + latin:keyLabel="ო" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <!-- U+10DE: "პ" GEORGIAN LETTER PAR --> + <Key + latin:keyLabel="პ" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_georgian2.xml b/java/res/xml/rowkeys_georgian2.xml new file mode 100644 index 000000000..ddd375afa --- /dev/null +++ b/java/res/xml/rowkeys_georgian2.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <Key + latin:keyLabel="A" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10E8: "შ" GEORGIAN LETTER SHIN --> + <Key + latin:keyLabel="შ" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="D" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="F" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="G" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="H" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10DF: "ჟ" GEORGIAN LETTER ZHAR --> + <Key + latin:keyLabel="ჟ" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="K" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="L" + latin:keyLabelFlags="preserveCase" /> + </case> + <default> + <!-- U+10D0: "ა" GEORGIAN LETTER AN + U+10FA: "ჺ" GEORGIAN LETTER AIN --> + <Key + latin:keyLabel="ა" + latin:moreKeys="ჺ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10E1: "ს" GEORGIAN LETTER SAN --> + <Key + latin:keyLabel="ს" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10D3: "დ" GEORGIAN LETTER DON --> + <Key + latin:keyLabel="დ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10E4: "ფ" GEORGIAN LETTER PHAR + U+10F6: "ჶ" GEORGIAN LETTER FI --> + <Key + latin:keyLabel="ფ" + latin:moreKeys="ჶ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10D2: "გ" GEORGIAN LETTER GAN + U+10F9: "ჹ" GEORGIAN LETTER TURNED GAN --> + <Key + latin:keyLabel="გ" + latin:moreKeys="ჹ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10F0: "ჰ" GEORGIAN LETTER HAE + U+10F5: "ჵ" GEORGIAN LETTER HOE --> + <Key + latin:keyLabel="ჰ" + latin:moreKeys="ჵ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10EF: "ჯ" GEORGIAN LETTER JHAN + U+10F7: "ჷ" GEORGIAN LETTER YN --> + <Key + latin:keyLabel="ჯ" + latin:moreKeys="ჷ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10D9: "კ" GEORGIAN LETTER KAN --> + <Key + latin:keyLabel="კ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10DA: "ლ" GEORGIAN LETTER LAS --> + <Key + latin:keyLabel="ლ" + latin:keyLabelFlags="preserveCase" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_georgian3.xml b/java/res/xml/rowkeys_georgian3.xml new file mode 100644 index 000000000..ae8443a31 --- /dev/null +++ b/java/res/xml/rowkeys_georgian3.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + <!-- U+10EB: "ძ" GEORGIAN LETTER JIL --> + <Key + latin:keyLabel="ძ" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="X" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10E9: "ჩ" GEORGIAN LETTER CHIN --> + <Key + latin:keyLabel="ჩ" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="V" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="B" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="N" + latin:keyLabelFlags="preserveCase" /> + <Key + latin:keyLabel="M" + latin:keyLabelFlags="preserveCase" /> + </case> + <default> + <!-- U+10D6: "ზ" GEORGIAN LETTER ZEN --> + <Key + latin:keyLabel="ზ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10EE: "ხ" GEORGIAN LETTER XAN + U+10F4: "ჴ" GEORGIAN LETTER HAR --> + <Key + latin:keyLabel="ხ" + latin:moreKeys="ჴ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10EA: "ც" GEORGIAN LETTER CAN --> + <Key + latin:keyLabel="ც" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10D5: "ვ" GEORGIAN LETTER VIN + U+10F3: "ჳ" GEORGIAN LETTER WE --> + <Key + latin:keyLabel="ვ" + latin:moreKeys="ჳ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10D1: "ბ" GEORGIAN LETTER BAN --> + <Key + latin:keyLabel="ბ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10DC: "ნ" GEORGIAN LETTER NAR + U+10FC: "ჼ" MODIFIER LETTER GEORGIAN NAR --> + <Key + latin:keyLabel="ნ" + latin:moreKeys="ჼ" + latin:keyLabelFlags="preserveCase" /> + <!-- U+10DB: "მ" GEORGIAN LETTER MAN --> + <Key + latin:keyLabel="მ" + latin:keyLabelFlags="preserveCase" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_greek1.xml b/java/res/xml/rowkeys_greek1.xml new file mode 100644 index 000000000..4df49f851 --- /dev/null +++ b/java/res/xml/rowkeys_greek1.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- TODO: Should find a way to compound Greek dialytika tonos and other Greek letters. --> + <!-- + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted" + > + U+0385: "΅" GREEK DIALYTIKA TONOS + <Key + latin:keyLabel="΅" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + </case> + <default> + --> + <!-- U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA --> + <Key + latin:keyLabel="ς" + latin:keyLabelFlags="preserveCase" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <!-- + </default> + </switch> + --> + <!-- U+03B5: "ε" GREEK SMALL LETTER EPSILON + U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS --> + <Key + latin:keyLabel="ε" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="έ" /> + <!-- U+03C1: "ρ" GREEK SMALL LETTER RHO --> + <Key + latin:keyLabel="ρ" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+03C4: "τ" GREEK SMALL LETTER TAU --> + <Key + latin:keyLabel="τ" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" /> + <!-- U+03C5: "υ" GREEK SMALL LETTER UPSILON + U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS + U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA + U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS --> + <Key + latin:keyLabel="υ" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" + latin:moreKeys="ύ,ϋ,ΰ" /> + <!-- U+03B8: "θ" GREEK SMALL LETTER THETA --> + <Key + latin:keyLabel="θ" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <!-- U+03B9: "ι" GREEK SMALL LETTER IOTA + U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS + U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA + U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS --> + <Key + latin:keyLabel="ι" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="ί,ϊ,ΐ" /> + <!-- U+03BF: "ο" GREEK SMALL LETTER OMICRON + U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS --> + <Key + latin:keyLabel="ο" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" + latin:moreKeys="ό" /> + <!-- U+03C0: "π" GREEK SMALL LETTER PI --> + <Key + latin:keyLabel="π" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> +</merge> diff --git a/java/res/xml/rowkeys_greek2.xml b/java/res/xml/rowkeys_greek2.xml new file mode 100644 index 000000000..91bdc1165 --- /dev/null +++ b/java/res/xml/rowkeys_greek2.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+03B1: "α" GREEK SMALL LETTER ALPHA + U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS --> + <Key + latin:keyLabel="α" + latin:moreKeys="ά" /> + <!-- U+03C3: "σ" GREEK SMALL LETTER SIGMA --> + <Key + latin:keyLabel="σ" /> + <!-- U+03B4: "δ" GREEK SMALL LETTER DELTA --> + <Key + latin:keyLabel="δ" /> + <!-- U+03C6: "φ" GREEK SMALL LETTER PHI --> + <Key + latin:keyLabel="φ" /> + <!-- U+03B3: "γ" GREEK SMALL LETTER GAMMA --> + <Key + latin:keyLabel="γ" /> + <!-- U+03B7: "η" GREEK SMALL LETTER ETA + U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS --> + <Key + latin:keyLabel="η" + latin:moreKeys="ή" /> + <!-- U+03BE: "ξ" GREEK SMALL LETTER XI --> + <Key + latin:keyLabel="ξ" /> + <!-- U+03BA: "κ" GREEK SMALL LETTER KAPPA --> + <Key + latin:keyLabel="κ" /> + <!-- U+03BB: "λ" GREEK SMALL LETTER LAMDA --> + <Key + latin:keyLabel="λ" /> +</merge> diff --git a/java/res/xml/rowkeys_greek3.xml b/java/res/xml/rowkeys_greek3.xml new file mode 100644 index 000000000..8a99db925 --- /dev/null +++ b/java/res/xml/rowkeys_greek3.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+03B6: "ζ" GREEK SMALL LETTER ZETA --> + <Key + latin:keyLabel="ζ" /> + <!-- U+03C7: "χ" GREEK SMALL LETTER CHI --> + <Key + latin:keyLabel="χ" /> + <!-- U+03C8: "ψ" GREEK SMALL LETTER PSI --> + <Key + latin:keyLabel="ψ" /> + <!-- U+03C9: "ω" GREEK SMALL LETTER OMEGA + U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS --> + <Key + latin:keyLabel="ω" + latin:moreKeys="ώ" /> + <!-- U+03B2: "β" GREEK SMALL LETTER BETA --> + <Key + latin:keyLabel="β" /> + <!-- U+03BD: "ν" GREEK SMALL LETTER NU --> + <Key + latin:keyLabel="ν" /> + <!-- U+03BC: "μ" GREEK SMALL LETTER MU --> + <Key + latin:keyLabel="μ" /> +</merge> diff --git a/java/res/xml/rowkeys_hebrew1.xml b/java/res/xml/rowkeys_hebrew1.xml new file mode 100644 index 000000000..396da785e --- /dev/null +++ b/java/res/xml/rowkeys_hebrew1.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+05E7: "ק" HEBREW LETTER QOF --> + <Key + latin:keyLabel="ק" /> + <!-- U+05E8: "ר" HEBREW LETTER RESH --> + <Key + latin:keyLabel="ר" /> + <!-- U+05D0: "א" HEBREW LETTER ALEF --> + <Key + latin:keyLabel="א" /> + <!-- U+05D8: "ט" HEBREW LETTER TET --> + <Key + latin:keyLabel="ט" /> + <!-- U+05D5: "ו" HEBREW LETTER VAV --> + <Key + latin:keyLabel="ו" /> + <!-- U+05DF: "ן" HEBREW LETTER FINAL NUN --> + <Key + latin:keyLabel="ן" /> + <!-- U+05DD: "ם" HEBREW LETTER FINAL MEM --> + <Key + latin:keyLabel="ם" /> + <!-- U+05E4: "פ" HEBREW LETTER PE --> + <Key + latin:keyLabel="פ" /> +</merge> diff --git a/java/res/xml/rowkeys_hebrew2.xml b/java/res/xml/rowkeys_hebrew2.xml new file mode 100644 index 000000000..e4ecac335 --- /dev/null +++ b/java/res/xml/rowkeys_hebrew2.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+05E9: "ש" HEBREW LETTER SHIN --> + <Key + latin:keyLabel="ש" /> + <!-- U+05D3: "ד" HEBREW LETTER DALET --> + <Key + latin:keyLabel="ד" /> + <!-- U+05D2: "ג" HEBREW LETTER GIMEL + U+05D2 U+05F3: "ג׳" HEBREW LETTER GIMEL + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="ג" + latin:moreKeys="ג׳" /> + <!-- U+05DB: "כ" HEBREW LETTER KAF --> + <Key + latin:keyLabel="כ" /> + <!-- U+05E2: "ע" HEBREW LETTER AYIN --> + <Key + latin:keyLabel="ע" /> + <!-- U+05D9: "י" HEBREW LETTER YOD + U+05F2 U+05B7: "ײַ" HEBREW LIGATURE YIDDISH DOUBLE YOD + HEBREW POINT PATAH --> + <Key + latin:keyLabel="י" + latin:moreKeys="ײַ" /> + <!-- U+05D7: "ח" HEBREW LETTER HET + U+05D7 U+05F3: "ח׳" HEBREW LETTER HET + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="ח" + latin:moreKeys="ח׳" /> + <!-- U+05DC: "ל" HEBREW LETTER LAMED --> + <Key + latin:keyLabel="ל" /> + <!-- U+05DA: "ך" HEBREW LETTER FINAL KAF --> + <Key + latin:keyLabel="ך" /> + <!-- U+05E3: "ף" HEBREW LETTER FINAL PE --> + <Key + latin:keyLabel="ף" /> +</merge> diff --git a/java/res/xml/rowkeys_hebrew3.xml b/java/res/xml/rowkeys_hebrew3.xml new file mode 100644 index 000000000..805a7a596 --- /dev/null +++ b/java/res/xml/rowkeys_hebrew3.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+05D6: "ז" HEBREW LETTER ZAYIN + U+05D6 U+05F3: "ז׳" HEBREW LETTER ZAYIN + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="ז" + latin:moreKeys="ז׳" /> + <!-- U+05E1: "ס" HEBREW LETTER SAMEKH --> + <Key + latin:keyLabel="ס" /> + <!-- U+05D1: "ב" HEBREW LETTER BET --> + <Key + latin:keyLabel="ב" /> + <!-- U+05D4: "ה" HEBREW LETTER HE --> + <Key + latin:keyLabel="ה" /> + <!-- U+05E0: "נ" HEBREW LETTER NUN --> + <Key + latin:keyLabel="נ" /> + <!-- U+05DE: "מ" HEBREW LETTER MEM --> + <Key + latin:keyLabel="מ" /> + <!-- U+05E6: "צ" HEBREW LETTER TSADI + U+05E6 U+05F3: "צ׳" HEBREW LETTER TSADI + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="צ" + latin:moreKeys="צ׳" /> + <!-- U+05EA: "ת" HEBREW LETTER TAV + U+05EA U+05F3: "ת׳" HEBREW LETTER TAV + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="ת" + latin:moreKeys="ת׳" /> + <!-- U+05E5: "ץ" HEBREW LETTER FINAL TSADI + U+05E5 U+05F3: "ץ׳" HEBREW LETTER FINAL TSADI + HEBREW PUNCTUATION GERESH --> + <Key + latin:keyLabel="ץ" + latin:moreKeys="ץ׳" /> +</merge> diff --git a/java/res/xml/rowkeys_nordic1.xml b/java/res/xml/rowkeys_nordic1.xml new file mode 100644 index 000000000..355b62654 --- /dev/null +++ b/java/res/xml/rowkeys_nordic1.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" /> + <Key + latin:keyLabel="@string/keylabel_for_scandinavia_row1_11" /> +</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_qwerty.xml b/java/res/xml/rowkeys_nordic2.xml index a2d26b3de..58e6bc2e7 100644 --- a/java/res/xml-sw600dp/kbd_rows_qwerty.xml +++ b/java/res/xml/rowkeys_nordic2.xml @@ -2,7 +2,7 @@ <!-- /* ** -** Copyright 2011, The Android Open Source Project +** Copyright 2012, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -22,13 +22,11 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row1" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row2" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row3" /> - <include - latin:keyboardLayout="@xml/kbd_qwerty_row4" /> + latin:keyboardLayout="@xml/rowkeys_qwerty2" /> + <Key + latin:keyLabel="@string/keylabel_for_scandinavia_row2_10" + latin:moreKeys="@string/more_keys_for_scandinavia_row2_10" /> + <Key + latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" + latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" /> </merge> diff --git a/java/res/xml/rowkeys_qwerty1.xml b/java/res/xml/rowkeys_qwerty1.xml new file mode 100644 index 000000000..bd5e9a271 --- /dev/null +++ b/java/res/xml/rowkeys_qwerty1.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="q" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <Key + latin:keyLabel="w" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <Key + latin:keyLabel="e" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="@string/more_keys_for_e" /> + <Key + latin:keyLabel="r" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" + latin:moreKeys="@string/more_keys_for_r" /> + <Key + latin:keyLabel="t" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" + latin:moreKeys="@string/more_keys_for_t" /> + <Key + latin:keyLabel="y" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" + latin:moreKeys="@string/more_keys_for_y" /> + <Key + latin:keyLabel="u" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" + latin:moreKeys="@string/more_keys_for_u" /> + <Key + latin:keyLabel="i" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="@string/more_keys_for_i" /> + <Key + latin:keyLabel="o" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" + latin:moreKeys="@string/more_keys_for_o" /> + <Key + latin:keyLabel="p" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> +</merge> diff --git a/java/res/xml/rowkeys_qwerty2.xml b/java/res/xml/rowkeys_qwerty2.xml new file mode 100644 index 000000000..4c983dfce --- /dev/null +++ b/java/res/xml/rowkeys_qwerty2.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="a" + latin:moreKeys="@string/more_keys_for_a" /> + <Key + latin:keyLabel="s" + latin:moreKeys="@string/more_keys_for_s" /> + <Key + latin:keyLabel="d" + latin:moreKeys="@string/more_keys_for_d" /> + <Key + latin:keyLabel="f" /> + <Key + latin:keyLabel="g" + latin:moreKeys="@string/more_keys_for_g" /> + <Key + latin:keyLabel="h" /> + <Key + latin:keyLabel="j" /> + <Key + latin:keyLabel="k" + latin:moreKeys="@string/more_keys_for_k" /> + <Key + latin:keyLabel="l" + latin:moreKeys="@string/more_keys_for_l" /> +</merge> diff --git a/java/res/xml/rowkeys_qwerty3.xml b/java/res/xml/rowkeys_qwerty3.xml new file mode 100644 index 000000000..932ea6f65 --- /dev/null +++ b/java/res/xml/rowkeys_qwerty3.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="z" + latin:moreKeys="@string/more_keys_for_z" /> + <Key + latin:keyLabel="x" /> + <Key + latin:keyLabel="c" + latin:moreKeys="@string/more_keys_for_c" /> + <Key + latin:keyLabel="v" + latin:moreKeys="@string/more_keys_for_v" /> + <Key + latin:keyLabel="b" /> + <Key + latin:keyLabel="n" + latin:moreKeys="@string/more_keys_for_n" /> + <Key + latin:keyLabel="m" /> +</merge> diff --git a/java/res/xml/rowkeys_qwertz1.xml b/java/res/xml/rowkeys_qwertz1.xml new file mode 100644 index 000000000..27b8a7653 --- /dev/null +++ b/java/res/xml/rowkeys_qwertz1.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="q" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <Key + latin:keyLabel="w" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <Key + latin:keyLabel="e" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="@string/more_keys_for_e" /> + <Key + latin:keyLabel="r" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" + latin:moreKeys="@string/more_keys_for_r" /> + <Key + latin:keyLabel="t" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" + latin:moreKeys="@string/more_keys_for_t" /> + <Key + latin:keyLabel="z" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" + latin:moreKeys="@string/more_keys_for_z" /> + <Key + latin:keyLabel="u" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" + latin:moreKeys="@string/more_keys_for_u" /> + <Key + latin:keyLabel="i" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="@string/more_keys_for_i" /> + <Key + latin:keyLabel="o" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" + latin:moreKeys="@string/more_keys_for_o" /> + <Key + latin:keyLabel="p" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> +</merge> diff --git a/java/res/xml/rowkeys_qwertz3.xml b/java/res/xml/rowkeys_qwertz3.xml new file mode 100644 index 000000000..d37cee67f --- /dev/null +++ b/java/res/xml/rowkeys_qwertz3.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="y" + latin:moreKeys="@string/more_keys_for_y" /> + <Key + latin:keyLabel="x" /> + <Key + latin:keyLabel="c" + latin:moreKeys="@string/more_keys_for_c" /> + <Key + latin:keyLabel="v" + latin:moreKeys="@string/more_keys_for_v" /> + <Key + latin:keyLabel="b" /> + <Key + latin:keyLabel="n" + latin:moreKeys="@string/more_keys_for_n" /> + <Key + latin:keyLabel="m" /> +</merge> diff --git a/java/res/xml/rowkeys_south_slavic1.xml b/java/res/xml/rowkeys_south_slavic1.xml new file mode 100644 index 000000000..5485d866e --- /dev/null +++ b/java/res/xml/rowkeys_south_slavic1.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0459: "љ" CYRILLIC SMALL LETTER LJE --> + <Key + latin:keyLabel="љ" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <!-- U+045A: "њ" CYRILLIC SMALL LETTER NJE --> + <Key + latin:keyLabel="њ" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" /> + <!-- U+0435: "е" CYRILLIC SMALL LETTER IE --> + <Key + latin:keyLabel="е" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3" + latin:moreKeys="@string/more_keys_for_cyrillic_ie" /> + <!-- U+0440: "р" CYRILLIC SMALL LETTER ER --> + <Key + latin:keyLabel="р" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4" /> + <!-- U+0442: "т" CYRILLIC SMALL LETTER TE --> + <Key + latin:keyLabel="т" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_ze" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6" /> + <!-- U+0443: "у" CYRILLIC SMALL LETTER U --> + <Key + latin:keyLabel="у" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7" /> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I --> + <Key + latin:keyLabel="и" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8" + latin:moreKeys="@string/more_keys_for_cyrillic_i" /> + <!-- U+043E: "о" CYRILLIC SMALL LETTER O --> + <Key + latin:keyLabel="о" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <!-- U+043F: "п" CYRILLIC SMALL LETTER PE --> + <Key + latin:keyLabel="п" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0" /> + <!-- U+0448: "ш" CYRILLIC SMALL LETTER SHA --> + <Key + latin:keyLabel="ш" /> +</merge> diff --git a/java/res/xml/rowkeys_south_slavic2.xml b/java/res/xml/rowkeys_south_slavic2.xml new file mode 100644 index 000000000..f30f42c1a --- /dev/null +++ b/java/res/xml/rowkeys_south_slavic2.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <!-- U+0430: "а" CYRILLIC SMALL LETTER A --> + <Key + latin:keyLabel="а" /> + <!-- U+0441: "с" CYRILLIC SMALL LETTER ES --> + <Key + latin:keyLabel="с" /> + <!-- U+0434: "д" CYRILLIC SMALL LETTER DE --> + <Key + latin:keyLabel="д" /> + <!-- U+0444: "ф" CYRILLIC SMALL LETTER EF --> + <Key + latin:keyLabel="ф" /> + <!-- U+0433: "г" CYRILLIC SMALL LETTER GHE --> + <Key + latin:keyLabel="г" /> + <!-- U+0445: "х" CYRILLIC SMALL LETTER HA --> + <Key + latin:keyLabel="х" /> + <!-- U+0458: "ј" CYRILLIC SMALL LETTER JE --> + <Key + latin:keyLabel="ј" /> + <!-- U+043A: "к" CYRILLIC SMALL LETTER KA --> + <Key + latin:keyLabel="к" /> + <!-- U+043B: "л" CYRILLIC SMALL LETTER EL --> + <Key + latin:keyLabel="л" /> + <!-- U+0447: "ч" CYRILLIC SMALL LETTER CHE --> + <Key + latin:keyLabel="ч" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_tshe" /> +</merge> diff --git a/java/res/xml/rowkeys_south_slavic3.xml b/java/res/xml/rowkeys_south_slavic3.xml new file mode 100644 index 000000000..303fad8c7 --- /dev/null +++ b/java/res/xml/rowkeys_south_slavic3.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_dze" /> + <!-- U+045F: "џ" CYRILLIC SMALL LETTER DZHE --> + <Key + latin:keyLabel="џ" /> + <!-- U+0446: "ц" CYRILLIC SMALL LETTER TSE --> + <Key + latin:keyLabel="ц" /> + <!-- U+0432: "в" CYRILLIC SMALL LETTER VE --> + <Key + latin:keyLabel="в" /> + <!-- U+0431: "б" CYRILLIC SMALL LETTER BE --> + <Key + latin:keyLabel="б" /> + <!-- U+043D: "н" CYRILLIC SMALL LETTER EN --> + <Key + latin:keyLabel="н" /> + <!-- U+043C: "м" CYRILLIC SMALL LETTER EM --> + <Key + latin:keyLabel="м" /> + <Key + latin:keyLabel="@string/keylabel_for_cyrillic_dje" /> + <!-- U+0436: "ж" CYRILLIC SMALL LETTER ZHE --> + <Key + latin:keyLabel="ж" /> +</merge> diff --git a/java/res/xml/rowkeys_spanish2.xml b/java/res/xml/rowkeys_spanish2.xml new file mode 100644 index 000000000..4c7e57997 --- /dev/null +++ b/java/res/xml/rowkeys_spanish2.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" /> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE --> + <Key + latin:keyLabel="ñ" /> + </merge> diff --git a/java/res/xml/rowkeys_symbols1.xml b/java/res/xml/rowkeys_symbols1.xml new file mode 100644 index 000000000..f6d6243d1 --- /dev/null +++ b/java/res/xml/rowkeys_symbols1.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="@string/keylabel_for_symbols_1" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_1" + latin:moreKeys="@string/more_keys_for_symbols_1" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_2" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_2" + latin:moreKeys="@string/more_keys_for_symbols_2" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_3" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_3" + latin:moreKeys="@string/more_keys_for_symbols_3" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_4" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_4" + latin:moreKeys="@string/more_keys_for_symbols_4" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_5" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_5" + latin:moreKeys="@string/more_keys_for_symbols_5" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_6" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_6" + latin:moreKeys="@string/more_keys_for_symbols_6" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_7" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_7" + latin:moreKeys="@string/more_keys_for_symbols_7" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_8" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_8" + latin:moreKeys="@string/more_keys_for_symbols_8" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_9" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_9" + latin:moreKeys="@string/more_keys_for_symbols_9" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_0" + latin:additionalMoreKeys="@string/additional_more_keys_for_symbols_0" + latin:moreKeys="@string/more_keys_for_symbols_0" /> +</merge> diff --git a/java/res/xml/rowkeys_symbols2.xml b/java/res/xml/rowkeys_symbols2.xml new file mode 100644 index 000000000..1092421d8 --- /dev/null +++ b/java/res/xml/rowkeys_symbols2.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="\@" /> + <Key + latin:keyLabel="\#" /> + <Key + latin:keyStyle="currencyKeyStyle" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_percent" + latin:moreKeys="@string/more_keys_for_symbols_percent" /> + <Key + latin:keyLabel="&" /> + <Key + latin:keyLabel="*" + latin:moreKeys="@string/more_keys_for_star" /> + <!-- U+2013: "–" EN DASH + U+2014: "—" EM DASH --> + <Key + latin:keyLabel="-" + latin:moreKeys="_,–,—" /> + <Key + latin:keyLabel="+" + latin:moreKeys="@string/more_keys_for_plus" /> + <include + latin:keyboardLayout="@xml/keys_parentheses" /> +</merge> diff --git a/java/res/xml/rowkeys_symbols3.xml b/java/res/xml/rowkeys_symbols3.xml new file mode 100644 index 000000000..1a484d416 --- /dev/null +++ b/java/res/xml/rowkeys_symbols3.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyStyle="toMoreSymbolKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <!-- U+00A1: "¡" INVERTED EXCLAMATION MARK --> + <Key + latin:keyLabel="!" + latin:moreKeys="¡" /> + <Key + latin:keyLabel=""" + latin:moreKeys="@string/more_keys_for_double_quote" /> + <Key + latin:keyLabel="\'" + latin:moreKeys="@string/more_keys_for_single_quote" /> + <Key + latin:keyLabel=":" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_semicolon" + latin:moreKeys="@string/more_keys_for_symbols_semicolon" /> + <Key + latin:keyLabel="/" /> + <Key + latin:keyLabel="@string/keylabel_for_symbols_question" + latin:moreKeys="@string/more_keys_for_symbols_question" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> +</merge> diff --git a/java/res/xml/rowkeys_symbols_shift1.xml b/java/res/xml/rowkeys_symbols_shift1.xml new file mode 100644 index 000000000..cc00aebcd --- /dev/null +++ b/java/res/xml/rowkeys_symbols_shift1.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyLabel="~" /> + <Key + latin:keyLabel="`" /> + <Key + latin:keyLabel="|" /> + <!-- U+2022: "•" BULLET --> + <Key + latin:keyLabel="•" + latin:moreKeys="@string/more_keys_for_bullet" /> + <!-- U+221A: "√" SQUARE ROOT --> + <Key + latin:keyLabel="√" /> + <!-- U+03C0: "π" GREEK SMALL LETTER PI --> + <Key + latin:keyLabel="π" + latin:moreKeys="Π" /> + <!-- U+00F7: "÷" DIVISION SIGN --> + <Key + latin:keyLabel="÷" /> + <!-- U+00D7: "×" MULTIPLICATION SIGN --> + <Key + latin:keyLabel="×" /> + <include + latin:keyboardLayout="@xml/keys_curly_brackets" /> +</merge> diff --git a/java/res/xml/rowkeys_symbols_shift2.xml b/java/res/xml/rowkeys_symbols_shift2.xml new file mode 100644 index 000000000..3fd8aacb6 --- /dev/null +++ b/java/res/xml/rowkeys_symbols_shift2.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyStyle="nonSpecialBackgroundTabKeyStyle" /> + <Key + latin:keyStyle="moreCurrency1KeyStyle" /> + <Key + latin:keyStyle="moreCurrency2KeyStyle" /> + <Key + latin:keyStyle="moreCurrency3KeyStyle" /> + <!-- U+00B0: "°" DEGREE SIGN + U+2032: "′" PRIME + U+2033: "″" DOUBLE PRIME --> + <Key + latin:keyLabel="°" + latin:moreKeys="′,″" /> + <!-- U+2191: "↑" UPWARDS ARROW + U+2193: "↓" DOWNWARDS ARROW + U+2190: "←" LEFTWARDS ARROW + U+2192: "→" RIGHTWARDS ARROW --> + <Key + latin:keyLabel="^" + latin:moreKeys="↑,↓,←,→" /> + <Key + latin:keyLabel="_" /> + <!-- U+2260: "≠" NOT EQUAL TO + U+2248: "≈" ALMOST EQUAL TO + U+221E: "∞" INFINITY --> + <Key + latin:keyLabel="=" + latin:moreKeys="≠,≈,∞" /> + <include + latin:keyboardLayout="@xml/keys_square_brackets" /> +</merge> diff --git a/java/res/xml/rowkeys_symbols_shift3.xml b/java/res/xml/rowkeys_symbols_shift3.xml new file mode 100644 index 000000000..f5db0fee6 --- /dev/null +++ b/java/res/xml/rowkeys_symbols_shift3.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Key + latin:keyStyle="backFromMoreSymbolKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <!-- U+2122: "™" TRADE MARK SIGN --> + <Key + latin:keyLabel="™" /> + <!-- U+00AE: "®" REGISTERED SIGN --> + <Key + latin:keyLabel="®" /> + <!-- U+00A9: "©" COPYRIGHT SIGN --> + <Key + latin:keyLabel="©" /> + <!-- U+00B6: "¶" PILCROW SIGN + U+00A7: "§" SECTION SIGN --> + <Key + latin:keyLabel="¶" + latin:moreKeys="§" /> + <Key + latin:keyLabel="\\" /> + <include + latin:keyboardLayout="@xml/keys_less_greater" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> +</merge> diff --git a/java/res/xml/rows_arabic.xml b/java/res/xml/rows_arabic.xml new file mode 100644 index 000000000..6449af219 --- /dev/null +++ b/java/res/xml/rows_arabic.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic3" + latin:keyXPos="5.0%p" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/kbd_qwerty_row3.xml b/java/res/xml/rows_azerty.xml index f2f137ea9..a52504c4f 100644 --- a/java/res/xml-sw768dp/kbd_qwerty_row3.xml +++ b/java/res/xml/rows_azerty.xml @@ -21,35 +21,34 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <include + latin:keyboardLayout="@xml/key_styles_common" /> <Row - latin:keyWidth="8.047%p" + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_azerty1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_azerty2" /> + </Row> + <Row + latin:keyWidth="10%p" > <Key latin:keyStyle="shiftKeyStyle" - latin:keyWidth="13.829%p"/> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> + latin:keyboardLayout="@xml/rowkeys_azerty3" /> <Key - latin:keyStyle="shiftKeyStyle" - latin:keyXPos="-13.750%p" - latin:keyWidth="fillBoth" /> + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> </merge> diff --git a/java/res/xml/rows_bulgarian.xml b/java/res/xml/rows_bulgarian.xml new file mode 100644 index 000000000..883c2833d --- /dev/null +++ b/java/res/xml/rows_bulgarian.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian1" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian2" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.636%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_east_slavic.xml b/java/res/xml/rows_east_slavic.xml new file mode 100644 index 000000000..019361250 --- /dev/null +++ b/java/res/xml/rows_east_slavic.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic1" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic2" /> + </Row> + <Row + latin:keyWidth="8.5%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="11.75%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_georgian.xml b/java/res/xml/rows_georgian.xml new file mode 100644 index 000000000..9bddfc785 --- /dev/null +++ b/java/res/xml/rows_georgian.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_georgian1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_georgian2" + latin:keyXPos="5%p" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_georgian3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" + latin:visualInsetsLeft="1%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_greek.xml b/java/res/xml/rows_greek.xml new file mode 100644 index 000000000..ca6d24005 --- /dev/null +++ b/java/res/xml/rows_greek.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/key_greek_semicolon" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_greek2" + latin:keyXPos="5%p" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_greek3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_hebrew.xml b/java/res/xml/rows_hebrew.xml new file mode 100644 index 000000000..2d513df65 --- /dev/null +++ b/java/res/xml/rows_hebrew.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew1" + latin:keyXPos="5%p" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew3" + latin:keyXPos="5%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/kbd_qwerty_row3.xml b/java/res/xml/rows_nordic.xml index c2b45e752..51d20e83f 100644 --- a/java/res/xml/kbd_qwerty_row3.xml +++ b/java/res/xml/rows_nordic.xml @@ -21,6 +21,20 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_nordic1" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_nordic2" /> + </Row> <Row latin:keyWidth="10%p" > @@ -28,27 +42,13 @@ latin:keyStyle="shiftKeyStyle" latin:keyWidth="15%p" latin:visualInsetsRight="1%p" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> <Key latin:keyStyle="deleteKeyStyle" latin:keyWidth="fillBoth" latin:visualInsetsLeft="1%p" /> </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> </merge> diff --git a/java/res/xml/rows_number.xml b/java/res/xml/rows_number.xml new file mode 100644 index 000000000..8da83be80 --- /dev/null +++ b/java/res/xml/rows_number.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2008, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:keyWidth="26.67%p" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_number" /> + <switch> + <case + latin:passwordInput="true" + > + <include + latin:keyboardLayout="@xml/rows_number_password" /> + </case> + <default> + <include + latin:keyboardLayout="@xml/rows_number_normal" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rows_number_normal.xml b/java/res/xml/rows_number_normal.xml new file mode 100644 index 000000000..6f9429cd8 --- /dev/null +++ b/java/res/xml/rows_number_normal.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> +<Key + latin:keyLabel="1" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="2" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="3" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="-" + latin:keyStyle="numFunctionalKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <Key + latin:keyLabel="4" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="5" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="6" + latin:keyStyle="numKeyStyle" /> + <switch> + <case + latin:mode="date" + > + <Key + latin:keyLabel="." + latin:keyStyle="numFunctionalKeyStyle" + latin:keyWidth="fillRight" /> + </case> + <case + latin:mode="time|datetime" + > + <Key + latin:keyLabel="." + latin:keyLabelFlags="hasPopupHint" + latin:moreKeys="@string/more_keys_for_am_pm" + latin:keyStyle="numFunctionalKeyStyle" + latin:keyWidth="fillRight" /> + </case> + <default> + <Key + latin:keyLabel="," + latin:keyStyle="numFunctionalKeyStyle" + latin:keyWidth="fillRight" /> + </default> + </switch> + </Row> + <Row> + <Key + latin:keyLabel="7" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyLabel="8" + latin:keyStyle="numKeyStyle"/> + <Key + latin:keyLabel="9" + latin:keyStyle="numKeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <Key + latin:keyStyle="numSpaceKeyStyle" /> + <Key + latin:keyLabel="0" + latin:keyStyle="numKeyStyle" /> + <switch> + <case + latin:mode="date" + > + <Key + latin:keyLabel="/" + latin:keyStyle="numKeyStyle" /> + </case> + <case + latin:mode="time" + > + <Key + latin:keyLabel=":" + latin:keyStyle="numKeyStyle" /> + </case> + <case + latin:mode="datetime" + > + <!-- U+002F: "/" SOLIDUS --> + <Key + latin:code="0x002F" + latin:keyLabel="/ :" + latin:moreKeys="!embeddedMoreKey!,:" + latin:keyStyle="numKeyStyle" /> + </case> + <default> + <Key + latin:keyLabel="." + latin:keyStyle="numKeyStyle" /> + </default> + </switch> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillRight" /> + </Row> +</merge> diff --git a/java/res/xml/rows_number_password.xml b/java/res/xml/rows_number_password.xml new file mode 100644 index 000000000..e4272ed3f --- /dev/null +++ b/java/res/xml/rows_number_password.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row> + <Key + latin:keyStyle="num1KeyStyle" /> + <Key + latin:keyStyle="num2KeyStyle" /> + <Key + latin:keyStyle="num3KeyStyle" /> + <Spacer /> + </Row> + <Row> + <Key + latin:keyStyle="num4KeyStyle" /> + <Key + latin:keyStyle="num5KeyStyle" /> + <Key + latin:keyStyle="num6KeyStyle" /> + <Spacer /> + </Row> + <Row> + <Key + latin:keyStyle="num7KeyStyle" /> + <Key + latin:keyStyle="num8KeyStyle" /> + <Key + latin:keyStyle="num9KeyStyle" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <Row> + <Spacer /> + <Key + latin:keyStyle="num0KeyStyle" /> + <Spacer /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillRight" /> + </Row> +</merge> diff --git a/java/res/xml/kbd_rows_phone.xml b/java/res/xml/rows_phone.xml index 5500a6078..630b24ea4 100644 --- a/java/res/xml/kbd_rows_phone.xml +++ b/java/res/xml/rows_phone.xml @@ -22,9 +22,9 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> + latin:keyboardLayout="@xml/key_styles_common" /> <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> + latin:keyboardLayout="@xml/key_styles_number" /> <Row> <Key latin:keyStyle="num1KeyStyle" /> @@ -62,13 +62,17 @@ </Row> <Row> <Key - latin:keyStyle="numSwitchToAltKeyStyle" /> + latin:keyStyle="numPhoneToSymbolKeyStyle" /> + <!-- U+0030: "0" DIGIT ZERO --> <Key - latin:keyStyle="num0KeyStyle" /> + latin:keyStyle="num0KeyStyle" + latin:code="0x0030" + latin:keyLabel="0 +" + latin:moreKeys="!embeddedMoreKey!,+" /> <Key latin:keyStyle="numSpaceKeyStyle" /> <Key - latin:keyStyle="returnKeyStyle" + latin:keyStyle="enterKeyStyle" latin:keyWidth="fillRight" /> </Row> </merge> diff --git a/java/res/xml/kbd_rows_phone_shift.xml b/java/res/xml/rows_phone_symbols.xml index 3c283d3e6..7841c56e5 100644 --- a/java/res/xml/kbd_rows_phone_shift.xml +++ b/java/res/xml/rows_phone_symbols.xml @@ -22,9 +22,9 @@ xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > <include - latin:keyboardLayout="@xml/kbd_key_styles" /> + latin:keyboardLayout="@xml/key_styles_common" /> <include - latin:keyboardLayout="@xml/kbd_numkey_styles" /> + latin:keyboardLayout="@xml/key_styles_number" /> <Row> <Key latin:keyLabel="(" @@ -42,13 +42,12 @@ </Row> <Row> <Key - latin:keyLabel="N" /> + latin:keyLabel="N" + latin:keyStyle="numKeyBaseStyle" /> <!-- Pause is a comma. Check PhoneNumberUtils.java to see if this has changed. --> <Key - latin:code="44" - latin:keyLabel="@string/label_pause_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" /> + latin:keyStyle="numPauseKeyStyle" /> <Key latin:keyLabel="," latin:keyStyle="numKeyStyle" /> @@ -62,9 +61,7 @@ latin:keyStyle="numStarKeyStyle" /> <!-- Wait is a semicolon. --> <Key - latin:code="59" - latin:keyLabel="@string/label_wait_key" - latin:keyLabelOption="followKeyHintLabelRatio|autoXScale" /> + latin:keyStyle="numWaitKeyStyle" /> <Key latin:keyLabel="#" latin:keyStyle="numKeyStyle" /> @@ -74,14 +71,14 @@ </Row> <Row> <Key - latin:keyStyle="numSwitchToNumericKeyStyle" /> + latin:keyStyle="numPhoneToNumericKeyStyle" /> <Key latin:keyLabel="+" latin:keyStyle="numKeyStyle" /> <Key latin:keyStyle="numSpaceKeyStyle" /> <Key - latin:keyStyle="returnKeyStyle" + latin:keyStyle="enterKeyStyle" latin:keyWidth="fillRight" /> </Row> </merge> diff --git a/java/res/xml/kbd_qwerty_row2.xml b/java/res/xml/rows_qwerty.xml index 8986780b7..716d10642 100644 --- a/java/res/xml/kbd_qwerty_row2.xml +++ b/java/res/xml/rows_qwerty.xml @@ -21,34 +21,35 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <include + latin:keyboardLayout="@xml/key_styles_common" /> <Row latin:keyWidth="10%p" > - <Key - latin:keyLabel="a" - latin:moreKeys="@string/more_keys_for_a" + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" latin:keyXPos="5%p" /> + </Row> + <Row + latin:keyWidth="10%p" + > <Key - latin:keyLabel="s" - latin:moreKeys="@string/more_keys_for_s" /> - <Key - latin:keyLabel="d" - latin:moreKeys="@string/more_keys_for_d" /> - <Key - latin:keyLabel="f" /> - <Key - latin:keyLabel="g" - latin:moreKeys="@string/more_keys_for_g" /> - <Key - latin:keyLabel="h" /> - <Key - latin:keyLabel="j" /> - <Key - latin:keyLabel="k" - latin:moreKeys="@string/more_keys_for_k" /> + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <!-- Here is 5%p space --> + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" + latin:visualInsetsLeft="1%p" /> </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> </merge> diff --git a/java/res/xml/rows_qwertz.xml b/java/res/xml/rows_qwertz.xml new file mode 100644 index 000000000..31a147c12 --- /dev/null +++ b/java/res/xml/rows_qwertz.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2010, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwertz1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty2" + latin:keyXPos="5%p" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwertz3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" + latin:visualInsetsLeft="1%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw600dp/kbd_qwerty_row3.xml b/java/res/xml/rows_south_slavic.xml index 4dabf633c..31bb38984 100644 --- a/java/res/xml-sw600dp/kbd_qwerty_row3.xml +++ b/java/res/xml/rows_south_slavic.xml @@ -21,33 +21,32 @@ <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" > + <include + latin:keyboardLayout="@xml/key_styles_common" /> <Row - latin:keyWidth="8.9%p" + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic1" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic2" /> + </Row> + <Row + latin:keyWidth="8.5%p" > <Key latin:keyStyle="shiftKeyStyle" - latin:keyWidth="10.0%p" /> - <Key - latin:keyLabel="z" - latin:moreKeys="@string/more_keys_for_z" /> - <Key - latin:keyLabel="x" /> - <Key - latin:keyLabel="c" - latin:moreKeys="@string/more_keys_for_c" /> - <Key - latin:keyLabel="v" - latin:moreKeys="@string/more_keys_for_v" /> - <Key - latin:keyLabel="b" /> - <Key - latin:keyLabel="n" - latin:moreKeys="@string/more_keys_for_n" /> - <Key - latin:keyLabel="m" /> + latin:keyWidth="11.75%p" /> <include - latin:keyboardLayout="@xml/kbd_row3_comma_period" /> - <include - latin:keyboardLayout="@xml/kbd_row3_smiley" /> + latin:keyboardLayout="@xml/rowkeys_south_slavic3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> </merge> diff --git a/java/res/xml/rows_spanish.xml b/java/res/xml/rows_spanish.xml new file mode 100644 index 000000000..b311297dd --- /dev/null +++ b/java/res/xml/rows_spanish.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_qwerty1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_spanish2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" + latin:visualInsetsLeft="1%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_symbols.xml b/java/res/xml/rows_symbols.xml new file mode 100644 index 000000000..dcd8d59d8 --- /dev/null +++ b/java/res/xml/rows_symbols.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2011, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols3" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols4" /> +</merge> diff --git a/java/res/xml/rows_symbols4.xml b/java/res/xml/rows_symbols4.xml new file mode 100644 index 000000000..3e26650e8 --- /dev/null +++ b/java/res/xml/rows_symbols4.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyWidth="15%p" /> + <switch> + <case + latin:hasShortcutKey="true" + > + <Key + latin:keyStyle="shortcutKeyStyle" /> + </case> + <!-- latin:hasShortcutKey="false" --> + <default> + <Key + latin:keyLabel="@string/keylabel_for_comma" + latin:keyLabelFlags="hasPopupHint" + latin:additionalMoreKeys="@string/more_keys_for_comma" + latin:keyStyle="f1MoreKeysStyle" /> + </default> + </switch> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="50%p" /> + <Key + latin:keyStyle="punctuationKeyStyle" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillRight" /> + </Row> +</merge> diff --git a/java/res/xml-fr-rCA/kbd_qwerty.xml b/java/res/xml/rows_symbols_shift.xml index 7bdfbadf1..6205eeddd 100644 --- a/java/res/xml-fr-rCA/kbd_qwerty.xml +++ b/java/res/xml/rows_symbols_shift.xml @@ -18,10 +18,31 @@ */ --> -<Keyboard +<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" - latin:keyboardLocale="fr_CA" > <include - latin:keyboardLayout="@xml/kbd_rows_qwerty" /> -</Keyboard> + latin:keyboardLayout="@xml/key_styles_common" /> + <include + latin:keyboardLayout="@xml/key_styles_currency" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_symbols_shift3" /> + </Row> + <include + latin:keyboardLayout="@xml/rows_symbols_shift4" /> +</merge> diff --git a/java/res/xml/rows_symbols_shift4.xml b/java/res/xml/rows_symbols_shift4.xml new file mode 100644 index 000000000..28b6ab8dc --- /dev/null +++ b/java/res/xml/rows_symbols_shift4.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<merge + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" +> + <Row + latin:keyWidth="10%p" + > + <Key + latin:keyStyle="toAlphaKeyStyle" + latin:keyWidth="15%p" /> + <!-- U+201F: "‟" DOUBLE HIGH-REVERSED-9 QUOTATION MARK --> + <!-- TODO: Neither DroidSans nor Roboto have the glyph for U+201F DOUBLE HIGH-REVERSED-9 QUOTATION MARK. --> + <!-- latin:keyLabelFlags="hasPopupHint" --> + <!-- latin:moreKeys="‟" --> + <!-- U+201E: "„" DOUBLE LOW-9 QUOTATION MARK --> + <Key + latin:keyLabel="„" + latin:backgroundType="functional" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="50%p" /> + <!-- U+2026: "…" HORIZONTAL ELLIPSIS --> + <Key + latin:keyLabel="…" + latin:backgroundType="functional" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillRight" /> + </Row> +</merge> diff --git a/java/res/xml/spell_checker_settings.xml b/java/res/xml/spell_checker_settings.xml index f402555c9..222b98b6b 100644 --- a/java/res/xml/spell_checker_settings.xml +++ b/java/res/xml/spell_checker_settings.xml @@ -18,9 +18,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/android_spell_checker_settings"> <CheckBoxPreference - android:key="use_proximity" - android:title="@string/use_proximity_option_title" - android:summary="@string/use_proximity_option_summary" + android:key="pref_spellcheck_use_contacts" + android:title="@string/use_contacts_for_spellchecking_option_title" + android:summary="@string/use_contacts_for_spellchecking_option_summary" android:persistent="true" android:defaultValue="true" /> </PreferenceScreen> diff --git a/java/res/xml/spellchecker.xml b/java/res/xml/spellchecker.xml index 30fac5b20..2e4448c44 100644 --- a/java/res/xml/spellchecker.xml +++ b/java/res/xml/spellchecker.xml @@ -17,11 +17,12 @@ */ --> -<!-- The attributes in this XML file provide the configuration information --> -<!-- for the spell checker --> +<!-- The attributes in this XML file provide the configuration information + for the spell checker --> <spell-checker xmlns:android="http://schemas.android.com/apk/res/android" - android:label="@string/spell_checker_service_name"> + android:label="@string/aosp_spell_checker_service_name" + android:settingsActivity="com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsActivity"> <subtype android:label="@string/subtype_generic" android:subtypeLocale="en" @@ -42,4 +43,16 @@ android:label="@string/subtype_generic" android:subtypeLocale="es" /> + <subtype + android:label="@string/subtype_generic" + android:subtypeLocale="ru" + /> + <subtype + android:label="@string/subtype_generic" + android:subtypeLocale="cs" + /> + <subtype + android:label="@string/subtype_generic" + android:subtypeLocale="nl" + /> </spell-checker> diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java new file mode 100644 index 000000000..dd43166af --- /dev/null +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -0,0 +1,376 @@ +/* + * 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.accessibility; + +import android.graphics.Rect; +import android.inputmethodservice.InputMethodService; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; +import android.support.v4.view.accessibility.AccessibilityRecordCompat; +import android.util.Log; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.view.accessibility.AccessibilityEvent; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardView; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Exposes a virtual view sub-tree for {@link KeyboardView} and generates + * {@link AccessibilityEvent}s for individual {@link Key}s. + * <p> + * A virtual sub-tree is composed of imaginary {@link View}s that are reported + * as a part of the view hierarchy for accessibility purposes. This enables + * custom views that draw complex content to report them selves as a tree of + * virtual views, thus conveying their logical structure. + * </p> + */ +public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat { + private static final String TAG = AccessibilityEntityProvider.class.getSimpleName(); + + private final KeyboardView mKeyboardView; + private final InputMethodService mInputMethodService; + private final KeyCodeDescriptionMapper mKeyCodeDescriptionMapper; + private final AccessibilityUtils mAccessibilityUtils; + + /** A map of integer IDs to {@link Key}s. */ + private final SparseArray<Key> mVirtualViewIdToKey = new SparseArray<Key>(); + + /** Temporary rect used to calculate in-screen bounds. */ + private final Rect mTempBoundsInScreen = new Rect(); + + /** The parent view's cached on-screen location. */ + private final int[] mParentLocation = new int[2]; + + public AccessibilityEntityProvider(KeyboardView keyboardView, InputMethodService inputMethod) { + mKeyboardView = keyboardView; + mInputMethodService = inputMethod; + + mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.getInstance(); + mAccessibilityUtils = AccessibilityUtils.getInstance(); + + assignVirtualViewIds(); + updateParentLocation(); + + // Ensure that the on-screen bounds are cleared when the layout changes. + mKeyboardView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); + } + + /** + * Creates and populates an {@link AccessibilityEvent} for the specified key + * and event type. + * + * @param key A key on the host keyboard view. + * @param eventType The event type to create. + * @return A populated {@link AccessibilityEvent} for the key. + * @see AccessibilityEvent + */ + public AccessibilityEvent createAccessibilityEvent(Key key, int eventType) { + final int virtualViewId = generateVirtualViewIdForKey(key); + final String keyDescription = getKeyDescription(key); + + final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + event.setPackageName(mKeyboardView.getContext().getPackageName()); + event.setClassName(key.getClass().getName()); + event.getText().add(keyDescription); + + final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); + record.setSource(mKeyboardView, virtualViewId); + + return event; + } + + /** + * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual + * view, i.e. a descendant of the host View, with the given <code>virtualViewId</code> or + * the host View itself if <code>virtualViewId</code> equals to {@link View#NO_ID}. + * <p> + * A virtual descendant is an imaginary View that is reported as a part of + * the view hierarchy for accessibility purposes. This enables custom views + * that draw complex content to report them selves as a tree of virtual + * views, thus conveying their logical structure. + * </p> + * <p> + * The implementer is responsible for obtaining an accessibility node info + * from the pool of reusable instances and setting the desired properties of + * the node info before returning it. + * </p> + * + * @param virtualViewId A client defined virtual view id. + * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual + * descendant or the host View. + * @see AccessibilityNodeInfoCompat + */ + @Override + public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) { + AccessibilityNodeInfoCompat info = null; + + if (virtualViewId == View.NO_ID) { + // We are requested to create an AccessibilityNodeInfo describing + // this View, i.e. the root of the virtual sub-tree. + info = AccessibilityNodeInfoCompat.obtain(mKeyboardView); + ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info); + + // Add the virtual children of the root View. + // TODO: Need to assign a unique ID to each key. + final Keyboard keyboard = mKeyboardView.getKeyboard(); + final Key[] keys = keyboard.mKeys; + for (Key key : keys) { + final int childVirtualViewId = generateVirtualViewIdForKey(key); + info.addChild(mKeyboardView, childVirtualViewId); + } + } else { + // Find the view that corresponds to the given id. + final Key key = mVirtualViewIdToKey.get(virtualViewId); + if (key == null) { + Log.e(TAG, "Invalid virtual view ID: " + virtualViewId); + return null; + } + + final String keyDescription = getKeyDescription(key); + final Rect boundsInParent = key.mHitBox; + + // Calculate the key's in-screen bounds. + mTempBoundsInScreen.set(boundsInParent); + mTempBoundsInScreen.offset(mParentLocation[0], mParentLocation[1]); + + final Rect boundsInScreen = mTempBoundsInScreen; + + // Obtain and initialize an AccessibilityNodeInfo with + // information about the virtual view. + info = AccessibilityNodeInfoCompat.obtain(); + info.addAction(AccessibilityNodeInfoCompat.ACTION_SELECT); + info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION); + info.setPackageName(mKeyboardView.getContext().getPackageName()); + info.setClassName(key.getClass().getName()); + info.setBoundsInParent(boundsInParent); + info.setBoundsInScreen(boundsInScreen); + info.setParent(mKeyboardView); + info.setSource(mKeyboardView, virtualViewId); + info.setBoundsInScreen(boundsInScreen); + info.setText(keyDescription); + } + + return info; + } + + /** + * Performs an accessibility action on a virtual view, i.e. a descendant of + * the host View, with the given <code>virtualViewId</code> or the host View itself if + * <code>virtualViewId</code> equals to {@link View#NO_ID}. + * + * @param action The action to perform. + * @param virtualViewId A client defined virtual view id. + * @return True if the action was performed. + * @see #createAccessibilityNodeInfo(int) + * @see AccessibilityNodeInfoCompat + */ + @Override + public boolean performAccessibilityAction(int action, int virtualViewId) { + if (virtualViewId == View.NO_ID) { + // Perform the action on the host View. + switch (action) { + case AccessibilityNodeInfoCompat.ACTION_SELECT: + if (!mKeyboardView.isSelected()) { + mKeyboardView.setSelected(true); + return mKeyboardView.isSelected(); + } + break; + case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION: + if (mKeyboardView.isSelected()) { + mKeyboardView.setSelected(false); + return !mKeyboardView.isSelected(); + } + break; + } + } else { + // Find the view that corresponds to the given id. + final Key child = mVirtualViewIdToKey.get(virtualViewId); + if (child == null) + return false; + + // Perform the action on a virtual view. + switch (action) { + case AccessibilityNodeInfoCompat.ACTION_SELECT: + // TODO: Provide some focus indicator. + return true; + case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION: + // TODO: Provide some clear focus indicator. + return true; + } + } + + return false; + } + + /** + * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case + * insensitive containment. The search is relative to the virtual view, i.e. + * a descendant of the host View, with the given <code>virtualViewId</code> or the host + * View itself <code>virtualViewId</code> equals to {@link View#NO_ID}. + * + * @param virtualViewId A client defined virtual view id which defined the + * root of the tree in which to perform the search. + * @param text The searched text. + * @return A list of node info. + * @see #createAccessibilityNodeInfo(int) + * @see AccessibilityNodeInfoCompat + */ + @Override + public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText( + String text, int virtualViewId) { + final String searchedLowerCase = text.toLowerCase(); + final Keyboard keyboard = mKeyboardView.getKeyboard(); + + List<AccessibilityNodeInfoCompat> results = null; + + if (virtualViewId == View.NO_ID) { + for (Key key : keyboard.mKeys) { + results = findByTextAndPopulate(searchedLowerCase, key, results); + } + } else { + final Key key = mVirtualViewIdToKey.get(virtualViewId); + + results = findByTextAndPopulate(searchedLowerCase, key, results); + } + + if (results == null) { + return Collections.emptyList(); + } + + return results; + } + + /** + * Helper method for {@link #findAccessibilityNodeInfosByText(String, int)}. + * Takes a current set of results and matches a specified key against a + * lower-case search string. Returns an updated list of results. + * + * @param searchedLowerCase The lower-case search string. + * @param key The key to compare against. + * @param results The current list of results, or {@code null} if no results + * found. + * @return An updated list of results, or {@code null} if no results found. + */ + private List<AccessibilityNodeInfoCompat> findByTextAndPopulate(String searchedLowerCase, + Key key, List<AccessibilityNodeInfoCompat> results) { + if (!keyContainsText(key, searchedLowerCase)) { + return results; + } + + final int childVirtualViewId = generateVirtualViewIdForKey(key); + final AccessibilityNodeInfoCompat nodeInfo = createAccessibilityNodeInfo( + childVirtualViewId); + + if (results == null) { + results = new LinkedList<AccessibilityNodeInfoCompat>(); + } + + results.add(nodeInfo); + + return results; + } + + /** + * Returns whether a key's current description contains the lower-case + * search text. + * + * @param key The key to compare against. + * @param textLowerCase The lower-case search string. + * @return {@code true} if the key contains the search text. + */ + private boolean keyContainsText(Key key, String textLowerCase) { + if (key == null) { + return false; + } + + final String description = getKeyDescription(key); + + if (description == null) { + return false; + } + + return description.toLowerCase().contains(textLowerCase); + } + + /** + * Returns the context-specific description for a {@link Key}. + * + * @param key The key to describe. + * @return The context-specific description of the key. + */ + private String getKeyDescription(Key key) { + final EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo(); + final boolean shouldObscure = mAccessibilityUtils.shouldObscureInput(editorInfo); + final String keyDescription = mKeyCodeDescriptionMapper.getDescriptionForKey( + mKeyboardView.getContext(), mKeyboardView.getKeyboard(), key, shouldObscure); + + return keyDescription; + } + + /** + * Assigns virtual view IDs to keyboard keys and populates the related maps. + */ + private void assignVirtualViewIds() { + final Keyboard keyboard = mKeyboardView.getKeyboard(); + if (keyboard == null) { + return; + } + + mVirtualViewIdToKey.clear(); + + final Key[] keys = keyboard.mKeys; + for (Key key : keys) { + final int virtualViewId = generateVirtualViewIdForKey(key); + mVirtualViewIdToKey.put(virtualViewId, key); + } + } + + /** + * Updates the parent's on-screen location. + */ + private void updateParentLocation() { + mKeyboardView.getLocationOnScreen(mParentLocation); + } + + /** + * Generates a virtual view identifier for the specified key. + * + * @param key The key to identify. + * @return A virtual view identifier. + */ + private static int generateVirtualViewIdForKey(Key key) { + // The key code is unique within an instance of a Keyboard. + return key.mCode; + } + + private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + assignVirtualViewIds(); + updateParentLocation(); + } + }; +} diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java index 46663327d..41da2aa4c 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java @@ -17,18 +17,18 @@ package com.android.inputmethod.accessibility; import android.content.Context; -import android.content.SharedPreferences; import android.inputmethodservice.InputMethodService; import android.media.AudioManager; import android.os.SystemClock; import android.provider.Settings; +import android.support.v4.view.MotionEventCompat; import android.util.Log; import android.view.MotionEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.EditorInfo; -import com.android.inputmethod.compat.AccessibilityManagerCompatWrapper; +import com.android.inputmethod.compat.AccessibilityManagerCompatUtils; import com.android.inputmethod.compat.AudioManagerCompatWrapper; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.MotionEventCompatUtils; @@ -45,7 +45,6 @@ public class AccessibilityUtils { private Context mContext; private AccessibilityManager mAccessibilityManager; - private AccessibilityManagerCompatWrapper mCompatManager; private AudioManagerCompatWrapper mAudioManager; /* @@ -55,15 +54,15 @@ public class AccessibilityUtils { */ private static final boolean ENABLE_ACCESSIBILITY = true; - public static void init(InputMethodService inputMethod, SharedPreferences prefs) { + public static void init(InputMethodService inputMethod) { if (!ENABLE_ACCESSIBILITY) return; // These only need to be initialized if the kill switch is off. - sInstance.initInternal(inputMethod, prefs); - KeyCodeDescriptionMapper.init(inputMethod, prefs); - AccessibleInputMethodServiceProxy.init(inputMethod, prefs); - AccessibleKeyboardViewProxy.init(inputMethod, prefs); + sInstance.initInternal(inputMethod); + KeyCodeDescriptionMapper.init(); + AccessibleInputMethodServiceProxy.init(inputMethod); + AccessibleKeyboardViewProxy.init(inputMethod); } public static AccessibilityUtils getInstance() { @@ -74,11 +73,10 @@ public class AccessibilityUtils { // This class is not publicly instantiable. } - private void initInternal(Context context, SharedPreferences prefs) { + private void initInternal(Context context) { mContext = context; mAccessibilityManager = (AccessibilityManager) context .getSystemService(Context.ACCESSIBILITY_SERVICE); - mCompatManager = new AccessibilityManagerCompatWrapper(mAccessibilityManager); final AudioManager audioManager = (AudioManager) context .getSystemService(Context.AUDIO_SERVICE); @@ -95,7 +93,7 @@ public class AccessibilityUtils { public boolean isTouchExplorationEnabled() { return ENABLE_ACCESSIBILITY && mAccessibilityManager.isEnabled() - && mCompatManager.isTouchExplorationEnabled(); + && AccessibilityManagerCompatUtils.isTouchExplorationEnabled(mAccessibilityManager); } /** @@ -111,17 +109,17 @@ public class AccessibilityUtils { return action == MotionEventCompatUtils.ACTION_HOVER_ENTER || action == MotionEventCompatUtils.ACTION_HOVER_EXIT - || action == MotionEventCompatUtils.ACTION_HOVER_MOVE; + || action == MotionEventCompat.ACTION_HOVER_MOVE; } /** * Returns whether the device should obscure typed password characters. * Typically this means speaking "dot" in place of non-control characters. - * + * * @return {@code true} if the device should obscure password characters. */ - public boolean shouldObscureInput(EditorInfo attribute) { - if (attribute == null) + public boolean shouldObscureInput(EditorInfo editorInfo) { + if (editorInfo == null) return false; // The user can optionally force speaking passwords. @@ -137,7 +135,7 @@ public class AccessibilityUtils { return false; // Don't speak if the IME is connected to a password field. - return InputTypeCompatUtils.isPasswordInputType(attribute.inputType); + return InputTypeCompatUtils.isPasswordInputType(editorInfo.inputType); } /** @@ -171,11 +169,11 @@ public class AccessibilityUtils { * Handles speaking the "connect a headset to hear passwords" notification * when connecting to a password field. * - * @param attribute The input connection's editor info attribute. + * @param editorInfo The input connection's editor info attribute. * @param restarting Whether the connection is being restarted. */ - public void onStartInputViewInternal(EditorInfo attribute, boolean restarting) { - if (shouldObscureInput(attribute)) { + public void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { + if (shouldObscureInput(editorInfo)) { final CharSequence text = mContext.getText(R.string.spoken_use_headphones); speak(text); } diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java index 4ab9cb898..961176bb8 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java @@ -17,31 +17,15 @@ package com.android.inputmethod.accessibility; import android.content.Context; -import android.content.SharedPreferences; import android.inputmethodservice.InputMethodService; import android.media.AudioManager; -import android.os.Looper; -import android.os.Message; import android.os.Vibrator; -import android.text.TextUtils; import android.view.KeyEvent; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; - -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.StaticInnerHandlerWrapper; public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener { private static final AccessibleInputMethodServiceProxy sInstance = new AccessibleInputMethodServiceProxy(); - /* - * Delay for the handler event that's fired when Accessibility is on and the - * user hovers outside of any valid keys. This is used to let the user know - * that if they lift their finger, nothing will be typed. - */ - private static final long DELAY_NO_HOVER_SELECTION = 250; - /** * Duration of the key click vibration in milliseconds. */ @@ -52,38 +36,9 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi private InputMethodService mInputMethod; private Vibrator mVibrator; private AudioManager mAudioManager; - private AccessibilityHandler mAccessibilityHandler; - private static class AccessibilityHandler - extends StaticInnerHandlerWrapper<AccessibleInputMethodServiceProxy> { - private static final int MSG_NO_HOVER_SELECTION = 0; - - public AccessibilityHandler(AccessibleInputMethodServiceProxy outerInstance, - Looper looper) { - super(outerInstance, looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_NO_HOVER_SELECTION: - getOuterInstance().notifyNoHoverSelection(); - break; - } - } - - public void postNoHoverSelection() { - removeMessages(MSG_NO_HOVER_SELECTION); - sendEmptyMessageDelayed(MSG_NO_HOVER_SELECTION, DELAY_NO_HOVER_SELECTION); - } - - public void cancelNoHoverSelection() { - removeMessages(MSG_NO_HOVER_SELECTION); - } - } - - public static void init(InputMethodService inputMethod, SharedPreferences prefs) { - sInstance.initInternal(inputMethod, prefs); + public static void init(InputMethodService inputMethod) { + sInstance.initInternal(inputMethod); } public static AccessibleInputMethodServiceProxy getInstance() { @@ -94,30 +49,10 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi // Not publicly instantiable. } - private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) { + private void initInternal(InputMethodService inputMethod) { mInputMethod = inputMethod; mVibrator = (Vibrator) inputMethod.getSystemService(Context.VIBRATOR_SERVICE); mAudioManager = (AudioManager) inputMethod.getSystemService(Context.AUDIO_SERVICE); - mAccessibilityHandler = new AccessibilityHandler(this, inputMethod.getMainLooper()); - } - - /** - * If touch exploration is enabled, cancels the event sent by - * {@link AccessibleInputMethodServiceProxy#onHoverExit(int)} because the - * user is currently hovering above a key. - */ - @Override - public void onHoverEnter(int primaryCode) { - mAccessibilityHandler.cancelNoHoverSelection(); - } - - /** - * If touch exploration is enabled, sends a delayed event to notify the user - * that they are not currently hovering above a key. - */ - @Override - public void onHoverExit(int primaryCode) { - mAccessibilityHandler.postNoHoverSelection(); } /** @@ -125,8 +60,6 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi */ @Override public void onFlickGesture(int direction) { - final int keyEventCode; - switch (direction) { case FlickGestureDetector.FLICK_LEFT: sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT); @@ -148,27 +81,4 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi mAudioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, FX_VOLUME); mInputMethod.sendDownUpKeyEvents(keyCode); } - - /** - * When Accessibility is turned on, notifies the user that they are not - * currently hovering above a key. By default this will speak the currently - * entered text. - */ - private void notifyNoHoverSelection() { - final ExtractedText extracted = mInputMethod.getCurrentInputConnection().getExtractedText( - new ExtractedTextRequest(), 0); - - if (extracted == null) - return; - - final CharSequence text; - - if (TextUtils.isEmpty(extracted.text)) { - text = mInputMethod.getString(R.string.spoken_no_text_entered); - } else { - text = mInputMethod.getString(R.string.spoken_current_text_is, extracted.text); - } - - AccessibilityUtils.getInstance().speak(text); - } } diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java index c1e92bec8..31d17d09f 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java @@ -18,24 +18,6 @@ package com.android.inputmethod.accessibility; public interface AccessibleKeyboardActionListener { /** - * Called when the user hovers inside a key. This is sent only when - * Accessibility is turned on. For keys that repeat, this is only called - * once. - * - * @param primaryCode the code of the key that was hovered over - */ - public void onHoverEnter(int primaryCode); - - /** - * Called when the user hovers outside a key. This is sent only when - * Accessibility is turned on. For keys that repeat, this is only called - * once. - * - * @param primaryCode the code of the key that was hovered over - */ - public void onHoverExit(int primaryCode); - - /** * @param direction the direction of the flick gesture, one of * <ul> * <li>{@link FlickGestureDetector#FLICK_UP} diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index cef82267f..2401d93c6 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -17,35 +17,39 @@ package com.android.inputmethod.accessibility; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Paint; import android.inputmethodservice.InputMethodService; -import android.util.Log; +import android.support.v4.view.AccessibilityDelegateCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.view.MotionEvent; +import android.view.View; import android.view.accessibility.AccessibilityEvent; -import android.view.inputmethod.EditorInfo; -import com.android.inputmethod.compat.AccessibilityEventCompatUtils; import com.android.inputmethod.compat.MotionEventCompatUtils; +import com.android.inputmethod.compat.ViewParentCompatUtils; import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.KeyDetector; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.LatinKeyboardView; import com.android.inputmethod.keyboard.PointerTracker; +import com.android.inputmethod.latin.R; -public class AccessibleKeyboardViewProxy { - private static final String TAG = AccessibleKeyboardViewProxy.class.getSimpleName(); +public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy(); private InputMethodService mInputMethod; private FlickGestureDetector mGestureDetector; private LatinKeyboardView mView; private AccessibleKeyboardActionListener mListener; + private AccessibilityEntityProvider mAccessibilityNodeProvider; - private int mLastHoverKeyIndex = KeyDetector.NOT_A_KEY; + private Key mLastHoverKey = null; - public static void init(InputMethodService inputMethod, SharedPreferences prefs) { - sInstance.initInternal(inputMethod, prefs); + public static void init(InputMethodService inputMethod) { + sInstance.initInternal(inputMethod); sInstance.mListener = AccessibleInputMethodServiceProxy.getInstance(); } @@ -53,15 +57,11 @@ public class AccessibleKeyboardViewProxy { return sInstance; } - public static void setView(LatinKeyboardView view) { - sInstance.mView = view; - } - private AccessibleKeyboardViewProxy() { // Not publicly instantiable. } - private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) { + private void initInternal(InputMethodService inputMethod) { final Paint paint = new Paint(); paint.setTextAlign(Paint.Align.LEFT); paint.setTextSize(14.0f); @@ -72,35 +72,39 @@ public class AccessibleKeyboardViewProxy { mGestureDetector = new KeyboardFlickGestureDetector(inputMethod); } - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event, - PointerTracker tracker) { - if (mView == null) { - Log.e(TAG, "No keyboard view set!"); - return false; + /** + * Sets the view wrapped by this proxy. + * + * @param view The view to wrap. + */ + public void setView(LatinKeyboardView view) { + if (view == null) { + // Ignore null views. + return; } - switch (event.getEventType()) { - case AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER: - final Key key = tracker.getKey(mLastHoverKeyIndex); - - if (key == null) - break; - - final EditorInfo info = mInputMethod.getCurrentInputEditorInfo(); - final boolean shouldObscure = AccessibilityUtils.getInstance().shouldObscureInput(info); - final CharSequence description = KeyCodeDescriptionMapper.getInstance() - .getDescriptionForKey(mView.getContext(), mView.getKeyboard(), key, - shouldObscure); + mView = view; - if (description == null) - return false; - - event.getText().add(description); + // Ensure that the view has an accessibility delegate. + ViewCompat.setAccessibilityDelegate(view, this); + } - break; + /** + * Proxy method for View.getAccessibilityNodeProvider(). This method is + * called in SDK version 15 and higher to obtain the virtual node hierarchy + * provider. + * + * @return The accessibility node provider for the current keyboard. + */ + @Override + public AccessibilityEntityProvider getAccessibilityNodeProvider(View host) { + // Instantiate the provide only when requested. Since the system + // will call this method multiple times it is a good practice to + // cache the provider instance. + if (mAccessibilityNodeProvider == null) { + mAccessibilityNodeProvider = new AccessibilityEntityProvider(mView, mInputMethod); } - - return true; + return mAccessibilityNodeProvider; } /** @@ -123,53 +127,94 @@ public class AccessibleKeyboardViewProxy { * @param event The touch exploration hover event. * @return {@code true} if the event was handled */ - /*package*/ boolean onHoverEventInternal(MotionEvent event, PointerTracker tracker) { + /* package */boolean onHoverEventInternal(MotionEvent event, PointerTracker tracker) { final int x = (int) event.getX(); final int y = (int) event.getY(); + final Key key = tracker.getKeyOn(x, y); + final Key previousKey = mLastHoverKey; + + mLastHoverKey = key; switch (event.getAction()) { case MotionEventCompatUtils.ACTION_HOVER_ENTER: - case MotionEventCompatUtils.ACTION_HOVER_MOVE: - final int keyIndex = tracker.getKeyIndexOn(x, y); - - if (keyIndex != mLastHoverKeyIndex) { - fireKeyHoverEvent(tracker, mLastHoverKeyIndex, false); - mLastHoverKeyIndex = keyIndex; - fireKeyHoverEvent(tracker, mLastHoverKeyIndex, true); + case MotionEventCompatUtils.ACTION_HOVER_EXIT: + return onHoverKey(key, event); + case MotionEventCompat.ACTION_HOVER_MOVE: + if (key != previousKey) { + return onTransitionKey(key, previousKey, event); + } else { + return onHoverKey(key, event); } - - return true; } return false; } - private void fireKeyHoverEvent(PointerTracker tracker, int keyIndex, boolean entering) { - if (mListener == null) { - Log.e(TAG, "No accessible keyboard action listener set!"); - return; - } + /** + * Simulates a transition between two {@link Key}s by sending a HOVER_EXIT + * on the previous key, a HOVER_ENTER on the current key, and a HOVER_MOVE + * on the current key. + * + * @param currentKey The currently hovered key. + * @param previousKey The previously hovered key. + * @param event The event that triggered the transition. + * @return {@code true} if the event was handled. + */ + private boolean onTransitionKey(Key currentKey, Key previousKey, MotionEvent event) { + final int savedAction = event.getAction(); - if (mView == null) { - Log.e(TAG, "No keyboard view set!"); - return; - } + event.setAction(MotionEventCompatUtils.ACTION_HOVER_EXIT); + onHoverKey(previousKey, event); - if (keyIndex == KeyDetector.NOT_A_KEY) - return; + event.setAction(MotionEventCompatUtils.ACTION_HOVER_ENTER); + onHoverKey(currentKey, event); - final Key key = tracker.getKey(keyIndex); + event.setAction(MotionEventCompat.ACTION_HOVER_MOVE); + final boolean handled = onHoverKey(currentKey, event); - if (key == null) - return; + event.setAction(savedAction); + + return handled; + } + + /** + * Handles a hover event on a key. If {@link Key} extended View, this would + * be analogous to calling View.onHoverEvent(MotionEvent). + * + * @param key The currently hovered key. + * @param event The hover event. + * @return {@code true} if the event was handled. + */ + private boolean onHoverKey(Key key, MotionEvent event) { + // Null keys can't receive events. + if (key == null) { + return false; + } - if (entering) { - mListener.onHoverEnter(key.mCode); - mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_ENTER); - } else { - mListener.onHoverExit(key.mCode); - mView.sendAccessibilityEvent(AccessibilityEventCompatUtils.TYPE_VIEW_HOVER_EXIT); + switch (event.getAction()) { + case MotionEventCompatUtils.ACTION_HOVER_ENTER: + sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER); + break; + case MotionEventCompatUtils.ACTION_HOVER_EXIT: + sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT); + break; } + + return true; + } + + /** + * Populates and sends an {@link AccessibilityEvent} for the specified key. + * + * @param key The key to send an event for. + * @param eventType The type of event to send. + */ + private void sendAccessibilityEventForKey(Key key, int eventType) { + final AccessibilityEntityProvider nodeProvider = getAccessibilityNodeProvider(null); + final AccessibilityEvent event = nodeProvider.createAccessibilityEvent(key, eventType); + + // Propagates the event up the view hierarchy. + ViewParentCompatUtils.requestSendAccessibilityEvent(mView.getParent(), mView, event); } private class KeyboardFlickGestureDetector extends FlickGestureDetector { @@ -185,4 +230,71 @@ public class AccessibleKeyboardViewProxy { return true; } } + + /** + * Notifies the user of changes in the keyboard shift state. + */ + public void notifyShiftState() { + final Keyboard keyboard = mView.getKeyboard(); + final KeyboardId keyboardId = keyboard.mId; + final int elementId = keyboardId.mElementId; + final Context context = mView.getContext(); + final CharSequence text; + + switch (elementId) { + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: + text = context.getText(R.string.spoken_description_shiftmode_locked); + break; + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: + case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: + text = context.getText(R.string.spoken_description_shiftmode_on); + break; + default: + text = context.getText(R.string.spoken_description_shiftmode_off); + } + + AccessibilityUtils.getInstance().speak(text); + } + + /** + * Notifies the user of changes in the keyboard symbols state. + */ + public void notifySymbolsState() { + final Keyboard keyboard = mView.getKeyboard(); + final Context context = mView.getContext(); + final KeyboardId keyboardId = keyboard.mId; + final int elementId = keyboardId.mElementId; + final int resId; + + switch (elementId) { + case KeyboardId.ELEMENT_ALPHABET: + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: + resId = R.string.spoken_description_mode_alpha; + break; + case KeyboardId.ELEMENT_SYMBOLS: + case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: + resId = R.string.spoken_description_mode_symbol; + break; + case KeyboardId.ELEMENT_PHONE: + resId = R.string.spoken_description_mode_phone; + break; + case KeyboardId.ELEMENT_PHONE_SYMBOLS: + resId = R.string.spoken_description_mode_phone_shift; + break; + default: + resId = -1; + } + + if (resId < 0) { + return; + } + + final String text = context.getString(resId); + AccessibilityUtils.getInstance().speak(text); + } } diff --git a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java index 9d99e3131..eaa4ddff6 100644 --- a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java +++ b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java @@ -18,6 +18,7 @@ package com.android.inputmethod.accessibility; import android.content.Context; import android.os.Message; +import android.support.v4.view.MotionEventCompat; import android.view.MotionEvent; import android.view.ViewConfiguration; @@ -32,7 +33,7 @@ import com.android.inputmethod.latin.StaticInnerHandlerWrapper; * properties: * <ul> * <li>Begins with a {@link MotionEventCompatUtils#ACTION_HOVER_ENTER} event - * <li>Contains any number of {@link MotionEventCompatUtils#ACTION_HOVER_MOVE} + * <li>Contains any number of {@link MotionEventCompat#ACTION_HOVER_MOVE} * events * <li>Ends with a {@link MotionEventCompatUtils#ACTION_HOVER_EXIT} event * <li>Maximum duration of 250 milliseconds @@ -126,10 +127,9 @@ public abstract class FlickGestureDetector { } final float distanceSquare = calculateDistanceSquare(mCachedHoverEnter, event); - final long timeout = event.getEventTime() - mCachedHoverEnter.getEventTime(); switch (event.getAction()) { - case MotionEventCompatUtils.ACTION_HOVER_MOVE: + case MotionEventCompat.ACTION_HOVER_MOVE: // Consume all valid move events before timeout. return true; case MotionEventCompatUtils.ACTION_HOVER_EXIT: diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 7302830d4..3d861c231 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -17,8 +17,8 @@ package com.android.inputmethod.accessibility; import android.content.Context; -import android.content.SharedPreferences; import android.text.TextUtils; +import android.util.Log; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; @@ -28,6 +28,8 @@ import com.android.inputmethod.latin.R; import java.util.HashMap; public class KeyCodeDescriptionMapper { + private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName(); + // The resource ID of the string spoken for obscured keys private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot; @@ -39,14 +41,8 @@ public class KeyCodeDescriptionMapper { // Map of key codes to spoken description resource IDs private final HashMap<Integer, Integer> mKeyCodeMap; - // Map of shifted key codes to spoken description resource IDs - private final HashMap<Integer, Integer> mShiftedKeyCodeMap; - - // Map of shift-locked key codes to spoken description resource IDs - private final HashMap<Integer, Integer> mShiftLockedKeyCodeMap; - - public static void init(Context context, SharedPreferences prefs) { - sInstance.initInternal(context, prefs); + public static void init() { + sInstance.initInternal(); } public static KeyCodeDescriptionMapper getInstance() { @@ -56,40 +52,15 @@ public class KeyCodeDescriptionMapper { private KeyCodeDescriptionMapper() { mKeyLabelMap = new HashMap<CharSequence, Integer>(); mKeyCodeMap = new HashMap<Integer, Integer>(); - mShiftedKeyCodeMap = new HashMap<Integer, Integer>(); - mShiftLockedKeyCodeMap = new HashMap<Integer, Integer>(); } - private void initInternal(Context context, SharedPreferences prefs) { + private void initInternal() { // Manual label substitutions for key labels with no string resource mKeyLabelMap.put(":-)", R.string.spoken_description_smiley); // Symbols that most TTS engines can't speak - mKeyCodeMap.put((int) '.', R.string.spoken_description_period); - mKeyCodeMap.put((int) ',', R.string.spoken_description_comma); - mKeyCodeMap.put((int) '(', R.string.spoken_description_left_parenthesis); - mKeyCodeMap.put((int) ')', R.string.spoken_description_right_parenthesis); - mKeyCodeMap.put((int) ':', R.string.spoken_description_colon); - mKeyCodeMap.put((int) ';', R.string.spoken_description_semicolon); - mKeyCodeMap.put((int) '!', R.string.spoken_description_exclamation_mark); - mKeyCodeMap.put((int) '?', R.string.spoken_description_question_mark); - mKeyCodeMap.put((int) '\"', R.string.spoken_description_double_quote); - mKeyCodeMap.put((int) '\'', R.string.spoken_description_single_quote); - mKeyCodeMap.put((int) '*', R.string.spoken_description_star); - mKeyCodeMap.put((int) '#', R.string.spoken_description_pound); mKeyCodeMap.put((int) ' ', R.string.spoken_description_space); - // Non-ASCII symbols (must use escape codes!) - mKeyCodeMap.put((int) '\u2022', R.string.spoken_description_dot); - mKeyCodeMap.put((int) '\u221A', R.string.spoken_description_square_root); - mKeyCodeMap.put((int) '\u03C0', R.string.spoken_description_pi); - mKeyCodeMap.put((int) '\u0394', R.string.spoken_description_delta); - mKeyCodeMap.put((int) '\u2122', R.string.spoken_description_trademark); - mKeyCodeMap.put((int) '\u2105', R.string.spoken_description_care_of); - mKeyCodeMap.put((int) '\u2026', R.string.spoken_description_ellipsis); - mKeyCodeMap.put((int) '\u201E', R.string.spoken_description_low_double_quote); - mKeyCodeMap.put((int) '\uFF0A', R.string.spoken_description_star); - // Special non-character codes defined in Keyboard mKeyCodeMap.put(Keyboard.CODE_DELETE, R.string.spoken_description_delete); mKeyCodeMap.put(Keyboard.CODE_ENTER, R.string.spoken_description_return); @@ -98,12 +69,6 @@ public class KeyCodeDescriptionMapper { mKeyCodeMap.put(Keyboard.CODE_SHORTCUT, R.string.spoken_description_mic); mKeyCodeMap.put(Keyboard.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol); mKeyCodeMap.put(Keyboard.CODE_TAB, R.string.spoken_description_tab); - - // Shifted versions of non-character codes defined in Keyboard - mShiftedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_shift_shifted); - - // Shift-locked versions of non-character codes defined in Keyboard - mShiftLockedKeyCodeMap.put(Keyboard.CODE_SHIFT, R.string.spoken_description_caps_lock); } /** @@ -125,27 +90,31 @@ public class KeyCodeDescriptionMapper { * @return a character sequence describing the action performed by pressing * the key */ - public CharSequence getDescriptionForKey(Context context, Keyboard keyboard, Key key, + public String getDescriptionForKey(Context context, Keyboard keyboard, Key key, boolean shouldObscure) { - if (key.mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - final CharSequence description = getDescriptionForSwitchAlphaSymbol(context, keyboard); + final int code = key.mCode; + + if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard); if (description != null) return description; } + if (code == Keyboard.CODE_SHIFT) { + return getDescriptionForShiftKey(context, keyboard); + } + if (!TextUtils.isEmpty(key.mLabel)) { final String label = key.mLabel.toString().trim(); + // First, attempt to map the label to a pre-defined description. if (mKeyLabelMap.containsKey(label)) { return context.getString(mKeyLabelMap.get(label)); - } else if (label.length() == 1 - || (keyboard.isManualTemporaryUpperCase() && !TextUtils - .isEmpty(key.mHintLabel))) { - return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); - } else { - return label; } - } else if (key.mCode != Keyboard.CODE_DUMMY) { + } + + // Just attempt to speak the description. + if (key.mCode != Keyboard.CODE_UNSPECIFIED) { return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); } @@ -162,36 +131,64 @@ public class KeyCodeDescriptionMapper { * @return a character sequence describing the action performed by pressing * the key */ - private CharSequence getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) { - final KeyboardId id = keyboard.mId; - - if (id.isAlphabetKeyboard()) { - return context.getString(R.string.spoken_description_to_symbol); - } else if (id.isSymbolsKeyboard()) { - return context.getString(R.string.spoken_description_to_alpha); - } else if (id.isPhoneShiftKeyboard()) { - return context.getString(R.string.spoken_description_to_numeric); - } else if (id.isPhoneKeyboard()) { - return context.getString(R.string.spoken_description_to_symbol); - } else { + private String getDescriptionForSwitchAlphaSymbol(Context context, Keyboard keyboard) { + final KeyboardId keyboardId = keyboard.mId; + final int elementId = keyboardId.mElementId; + final int resId; + + switch (elementId) { + case KeyboardId.ELEMENT_ALPHABET: + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: + resId = R.string.spoken_description_to_symbol; + break; + case KeyboardId.ELEMENT_SYMBOLS: + case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: + resId = R.string.spoken_description_to_alpha; + break; + case KeyboardId.ELEMENT_PHONE: + resId = R.string.spoken_description_to_symbol; + break; + case KeyboardId.ELEMENT_PHONE_SYMBOLS: + resId = R.string.spoken_description_to_numeric; + break; + default: + Log.e(TAG, "Missing description for keyboard element ID:" + elementId); return null; } + + return context.getString(resId); } /** - * Returns the keycode for the specified key given the current keyboard - * state. + * Returns a context-sensitive description of the "Shift" key. * + * @param context The package's context. * @param keyboard The keyboard on which the key resides. - * @param key The key from which to obtain a key code. - * @return the key code for the specified key + * @return A context-sensitive description of the "Shift" key. */ - private int getCorrectKeyCode(Keyboard keyboard, Key key) { - if (keyboard.isManualTemporaryUpperCase() && !TextUtils.isEmpty(key.mHintLabel)) { - return key.mHintLabel.charAt(0); - } else { - return key.mCode; + private String getDescriptionForShiftKey(Context context, Keyboard keyboard) { + final KeyboardId keyboardId = keyboard.mId; + final int elementId = keyboardId.mElementId; + final int resId; + + switch (elementId) { + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: + resId = R.string.spoken_description_caps_lock; + break; + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: + case KeyboardId.ELEMENT_SYMBOLS_SHIFTED: + resId = R.string.spoken_description_shift_shifted; + break; + default: + resId = R.string.spoken_description_shift; } + + return context.getString(resId); } /** @@ -215,15 +212,9 @@ public class KeyCodeDescriptionMapper { * @return a character sequence describing the action performed by pressing * the key */ - private CharSequence getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key, + private String getDescriptionForKeyCode(Context context, Keyboard keyboard, Key key, boolean shouldObscure) { - final int code = getCorrectKeyCode(keyboard, key); - - if (keyboard.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) { - return context.getString(mShiftLockedKeyCodeMap.get(code)); - } else if (keyboard.isShiftedOrShiftLocked() && mShiftedKeyCodeMap.containsKey(code)) { - return context.getString(mShiftedKeyCodeMap.get(code)); - } + final int code = key.mCode; // If the key description should be obscured, now is the time to do it. final boolean isDefinedNonCtrl = Character.isDefined(code) && !Character.isISOControl(code); diff --git a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java b/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java index 65949357f..2c31c55b0 100644 --- a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java @@ -24,7 +24,7 @@ public abstract class AbstractCompatWrapper { public AbstractCompatWrapper(Object obj) { if (obj == null) { - Log.e(TAG, "Invalid input to AbstructCompatWrapper"); + Log.e(TAG, "Invalid input to AbstractCompatWrapper"); } mObj = obj; } diff --git a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java b/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java deleted file mode 100644 index 2fa9d87d8..000000000 --- a/java/src/com/android/inputmethod/compat/AccessibilityEventCompatUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2011 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.compat; - -public class AccessibilityEventCompatUtils { - public static final int TYPE_VIEW_HOVER_ENTER = 0x80; - public static final int TYPE_VIEW_HOVER_EXIT = 0x100; -} diff --git a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatUtils.java index a30af0faf..41b6a074d 100644 --- a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatUtils.java @@ -20,17 +20,15 @@ import android.view.accessibility.AccessibilityManager; import java.lang.reflect.Method; -public class AccessibilityManagerCompatWrapper { +public class AccessibilityManagerCompatUtils { private static final Method METHOD_isTouchExplorationEnabled = CompatUtils.getMethod( AccessibilityManager.class, "isTouchExplorationEnabled"); - private final AccessibilityManager mManager; - - public AccessibilityManagerCompatWrapper(AccessibilityManager manager) { - mManager = manager; + private AccessibilityManagerCompatUtils() { + // This class is non-instantiable. } - public boolean isTouchExplorationEnabled() { - return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isTouchExplorationEnabled); + public static boolean isTouchExplorationEnabled(AccessibilityManager receiver) { + return (Boolean) CompatUtils.invoke(receiver, false, METHOD_isTouchExplorationEnabled); } } diff --git a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java index f6afbcfe2..011473bef 100644 --- a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java @@ -16,10 +16,14 @@ package com.android.inputmethod.compat; +import android.util.Log; + import java.lang.reflect.Method; import java.util.Arrays; public class ArraysCompatUtils { + private static final String TAG = ArraysCompatUtils.class.getSimpleName(); + private static final Method METHOD_Arrays_binarySearch = CompatUtils .getMethod(Arrays.class, "binarySearch", int[].class, int.class, int.class, int.class); @@ -33,8 +37,15 @@ public class ArraysCompatUtils { } } - /* package */ static int compatBinarySearch(int[] array, int startIndex, int endIndex, - int value) { + // TODO: Implement fast binary search + /* package for testing */ + static int compatBinarySearch(int[] array, int startIndex, int endIndex, int value) { + // Output error log because this method has strict performance penalty. + // Note that this method has been called only from spell checker and spell checker exists + // only from IceCreamSandwich and after, so that there is no chance on pre-ICS device to + // invoke this method. + Log.e(TAG, "Invoked expensive binarySearch"); + if (startIndex > endIndex) throw new IllegalArgumentException(); if (startIndex < 0 || endIndex > array.length) throw new ArrayIndexOutOfBoundsException(); diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java index bcdcef7dc..938388d6c 100644 --- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java @@ -26,77 +26,88 @@ public class EditorInfoCompatUtils { EditorInfo.class, "IME_FLAG_NAVIGATE_NEXT"); private static final Field FIELD_IME_FLAG_NAVIGATE_PREVIOUS = CompatUtils.getField( EditorInfo.class, "IME_FLAG_NAVIGATE_PREVIOUS"); + private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_FORCE_ASCII"); private static final Field FIELD_IME_ACTION_PREVIOUS = CompatUtils.getField( EditorInfo.class, "IME_ACTION_PREVIOUS"); private static final Integer OBJ_IME_FLAG_NAVIGATE_NEXT = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_NEXT); private static final Integer OBJ_IME_FLAG_NAVIGATE_PREVIOUS = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_PREVIOUS); + private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII); private static final Integer OBJ_IME_ACTION_PREVIOUS = (Integer) CompatUtils .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS); + // EditorInfo.IME_FLAG_NAVIGATE_NEXT has been introduced since API#11 (Honeycomb). public static boolean hasFlagNavigateNext(int imeOptions) { if (OBJ_IME_FLAG_NAVIGATE_NEXT == null) return false; return (imeOptions & OBJ_IME_FLAG_NAVIGATE_NEXT) != 0; } + // EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS has been introduced since API#11 (Honeycomb). public static boolean hasFlagNavigatePrevious(int imeOptions) { if (OBJ_IME_FLAG_NAVIGATE_PREVIOUS == null) return false; return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0; } - public static void performEditorActionNext(InputConnection ic) { - ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean). + public static boolean hasFlagForceAscii(int imeOptions) { + if (OBJ_IME_FLAG_FORCE_ASCII == null) + return false; + return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0; } + // EditorInfo.IME_ACTION_PREVIOUS has been introduced since API#11 (Honeycomb). public static void performEditorActionPrevious(InputConnection ic) { - if (OBJ_IME_ACTION_PREVIOUS == null) + if (OBJ_IME_ACTION_PREVIOUS == null || ic == null) return; ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS); } - public static String imeOptionsName(int imeOptions) { - if (imeOptions == -1) - return null; + public static String imeActionName(int imeOptions) { final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION; - final String action; switch (actionId) { - case EditorInfo.IME_ACTION_UNSPECIFIED: - action = "actionUnspecified"; - break; - case EditorInfo.IME_ACTION_NONE: - action = "actionNone"; - break; - case EditorInfo.IME_ACTION_GO: - action = "actionGo"; - break; - case EditorInfo.IME_ACTION_SEARCH: - action = "actionSearch"; - break; - case EditorInfo.IME_ACTION_SEND: - action = "actionSend"; - break; - case EditorInfo.IME_ACTION_NEXT: - action = "actionNext"; - break; - case EditorInfo.IME_ACTION_DONE: - action = "actionDone"; - break; - default: { - if (OBJ_IME_ACTION_PREVIOUS != null && actionId == OBJ_IME_ACTION_PREVIOUS) { - action = "actionPrevious"; - } else { - action = "actionUnknown(" + actionId + ")"; - } - break; + case EditorInfo.IME_ACTION_UNSPECIFIED: + return "actionUnspecified"; + case EditorInfo.IME_ACTION_NONE: + return "actionNone"; + case EditorInfo.IME_ACTION_GO: + return "actionGo"; + case EditorInfo.IME_ACTION_SEARCH: + return "actionSearch"; + case EditorInfo.IME_ACTION_SEND: + return "actionSend"; + case EditorInfo.IME_ACTION_NEXT: + return "actionNext"; + case EditorInfo.IME_ACTION_DONE: + return "actionDone"; + default: + if (OBJ_IME_ACTION_PREVIOUS != null && actionId == OBJ_IME_ACTION_PREVIOUS) { + return "actionPrevious"; + } else { + return "actionUnknown(" + actionId + ")"; } } + } + + public static String imeOptionsName(int imeOptions) { + final String action = imeActionName(imeOptions); + final StringBuilder flags = new StringBuilder(); if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { - return "flagNoEnterAction|" + action; - } else { - return action; + flags.append("flagNoEnterAction|"); + } + if (hasFlagNavigateNext(imeOptions)) { + flags.append("flagNavigateNext|"); + } + if (hasFlagNavigatePrevious(imeOptions)) { + flags.append("flagNavigatePrevious|"); + } + if (hasFlagForceAscii(imeOptions)) { + flags.append("flagForceAscii|"); } + return (action != null) ? flags + action : flags.toString(); } } diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index 51dc4cd37..bf5f20158 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -32,7 +32,7 @@ import android.view.inputmethod.InputMethodManager; import com.android.inputmethod.deprecated.LanguageSwitcherProxy; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.SubtypeUtils; import java.lang.reflect.Method; import java.util.ArrayList; @@ -49,6 +49,8 @@ public class InputMethodManagerCompatWrapper { private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName(); private static final Method METHOD_getCurrentInputMethodSubtype = CompatUtils.getMethod(InputMethodManager.class, "getCurrentInputMethodSubtype"); + private static final Method METHOD_getLastInputMethodSubtype = + CompatUtils.getMethod(InputMethodManager.class, "getLastInputMethodSubtype"); private static final Method METHOD_getEnabledInputMethodSubtypeList = CompatUtils.getMethod(InputMethodManager.class, "getEnabledInputMethodSubtypeList", InputMethodInfo.class, boolean.class); @@ -60,6 +62,8 @@ public class InputMethodManagerCompatWrapper { String.class, InputMethodSubtypeCompatWrapper.CLASS_InputMethodSubtype); private static final Method METHOD_switchToLastInputMethod = CompatUtils.getMethod( InputMethodManager.class, "switchToLastInputMethod", IBinder.class); + private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod( + InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE); private static final InputMethodManagerCompatWrapper sInstance = new InputMethodManagerCompatWrapper(); @@ -111,6 +115,15 @@ public class InputMethodManagerCompatWrapper { return new InputMethodSubtypeCompatWrapper(o); } + public InputMethodSubtypeCompatWrapper getLastInputMethodSubtype() { + if (!SUBTYPE_SUPPORTED) { + return new InputMethodSubtypeCompatWrapper( + 0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, ""); + } + Object o = CompatUtils.invoke(mImm, null, METHOD_getLastInputMethodSubtype); + return new InputMethodSubtypeCompatWrapper(o); + } + public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList( InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) { if (!SUBTYPE_SUPPORTED) { @@ -150,11 +163,10 @@ public class InputMethodManagerCompatWrapper { private InputMethodInfoCompatWrapper getLatinImeInputMethodInfo() { if (TextUtils.isEmpty(mLatinImePackageName)) return null; - return Utils.getInputMethodInfo(this, mLatinImePackageName); + return SubtypeUtils.getInputMethodInfo(mLatinImePackageName); } - @SuppressWarnings("unused") - private InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) { + private static InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) { if (VOICE_MODE.equals(mode) && !FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) return null; Locale inputLocale = SubtypeSwitcher.getInstance().getInputLocale(); @@ -222,6 +234,14 @@ public class InputMethodManagerCompatWrapper { return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token); } + public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { + if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) { + return true; + } + return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, + onlyCurrentIme); + } + public List<InputMethodInfoCompatWrapper> getEnabledInputMethodList() { if (mImm == null) return null; List<InputMethodInfoCompatWrapper> imis = new ArrayList<InputMethodInfoCompatWrapper>(); @@ -240,8 +260,8 @@ public class InputMethodManagerCompatWrapper { // The code below are based on {@link InputMethodManager#showInputMethodMenuInternal}. - final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( - this, mLatinImePackageName); + final InputMethodInfoCompatWrapper myImi = SubtypeUtils.getInputMethodInfo( + mLatinImePackageName); final List<InputMethodSubtypeCompatWrapper> myImsList = getEnabledInputMethodSubtypeList( myImi, true); final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype(); diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java index a6bb83adf..574158825 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java @@ -29,7 +29,7 @@ import java.util.Locale; // TODO: Override this class with the concrete implementation if we need to take care of the // performance. -public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper { +public class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName(); private static final String DEFAULT_LOCALE = "en_US"; @@ -65,7 +65,7 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper public InputMethodSubtypeCompatWrapper(Object subtype) { super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype)) - ? subtype : null); + ? subtype : new Object()); mDummyNameResId = 0; mDummyIconResId = 0; mDummyLocale = DEFAULT_LOCALE; @@ -76,7 +76,7 @@ public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper // Constructor for creating a dummy subtype. public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale, String mode, String extraValues) { - super(null); + super(new Object()); if (DBG) { Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper"); } diff --git a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java index 8518a4a78..9a523011a 100644 --- a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java @@ -17,7 +17,7 @@ package com.android.inputmethod.compat; public class MotionEventCompatUtils { - public static final int ACTION_HOVER_MOVE = 0x7; + // TODO: Remove after these are added to MotionEventCompat. public static final int ACTION_HOVER_ENTER = 0x9; public static final int ACTION_HOVER_EXIT = 0xA; } diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index 161ef09b8..e82d91411 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -50,19 +50,19 @@ public class SuggestionSpanUtils { .getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan); public static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION"); - public static final Field FIELD_SUGGESTION_MAX_SIZE + public static final Field FIELD_SUGGESTIONS_MAX_SIZE = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE"); public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION);; - public static final Integer OBJ_SUGGESTION_MAX_SIZE = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_SUGGESTION_MAX_SIZE);; + public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE);; static { SUGGESTION_SPAN_IS_SUPPORTED = CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null; if (LatinImeLogger.sDBG) { if (SUGGESTION_SPAN_IS_SUPPORTED - && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null)) { + && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null)) { throw new RuntimeException("Field is accidentially null."); } } @@ -71,7 +71,7 @@ public class SuggestionSpanUtils { public static CharSequence getTextWithAutoCorrectionIndicatorUnderline( Context context, CharSequence text) { if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null - || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTION_MAX_SIZE == null) { + || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null) { return text; } final Spannable spannable = text instanceof Spannable @@ -93,8 +93,7 @@ public class SuggestionSpanUtils { CharSequence pickedWord, SuggestedWords suggestedWords) { if (TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null || suggestedWords == null || suggestedWords.size() == 0 - || suggestedWords.getInfo(0).isObsoleteSuggestedWord() - || OBJ_SUGGESTION_MAX_SIZE == null) { + || OBJ_SUGGESTIONS_MAX_SIZE == null) { return pickedWord; } @@ -106,7 +105,7 @@ public class SuggestionSpanUtils { } final ArrayList<String> suggestionsList = new ArrayList<String>(); for (int i = 0; i < suggestedWords.size(); ++i) { - if (suggestionsList.size() >= OBJ_SUGGESTION_MAX_SIZE) { + if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) { break; } final CharSequence word = suggestedWords.getWord(i); diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java new file mode 100644 index 000000000..6a0d4dd9e --- /dev/null +++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 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.compat; + +import android.view.textservice.SuggestionsInfo; + +import java.lang.reflect.Field; + +public class SuggestionsInfoCompatUtils { + private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField( + SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS"); + private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS);; + private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = + OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null + ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0; + + private SuggestionsInfoCompatUtils() { + } + + /** + * Returns the flag value of the attributes of the suggestions that can be obtained by + * {@link #getSuggestionsAttributes}: this tells that the text service thinks + * the result suggestions include highly recommended ones. + */ + public static int getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() { + return RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS; + } +} diff --git a/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java new file mode 100644 index 000000000..d19bc3af1 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/ViewParentCompatUtils.java @@ -0,0 +1,51 @@ +/* + * 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.compat; + +import android.view.View; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; + +import java.lang.reflect.Method; + +public class ViewParentCompatUtils { + private static final Method METHOD_requestSendAccessibilityEvent = CompatUtils.getMethod( + ViewParent.class, "requestSendAccessibilityEvent", View.class, + AccessibilityEvent.class); + + /** + * Called by a child to request from its parent to send an {@link AccessibilityEvent}. + * The child has already populated a record for itself in the event and is delegating + * to its parent to send the event. The parent can optionally add a record for itself. + * <p> + * Note: An accessibility event is fired by an individual view which populates the + * event with a record for its state and requests from its parent to perform + * the sending. The parent can optionally add a record for itself before + * dispatching the request to its parent. A parent can also choose not to + * respect the request for sending the event. The accessibility event is sent + * by the topmost view in the view tree.</p> + * + * @param child The child which requests sending the event. + * @param event The event to be sent. + * @return True if the event was sent. + */ + public static boolean requestSendAccessibilityEvent( + ViewParent receiver, View child, AccessibilityEvent event) { + return (Boolean) CompatUtils.invoke( + receiver, false, METHOD_requestSendAccessibilityEvent, child, event); + } +} diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java index 3f8c2ef8f..87d1c118b 100644 --- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java +++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java @@ -16,23 +16,6 @@ package com.android.inputmethod.deprecated; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; -import com.android.inputmethod.compat.SharedPreferencesCompat; -import com.android.inputmethod.deprecated.voice.FieldContext; -import com.android.inputmethod.deprecated.voice.Hints; -import com.android.inputmethod.deprecated.voice.SettingsUtil; -import com.android.inputmethod.deprecated.voice.VoiceInput; -import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.latin.EditingUtils; -import com.android.inputmethod.latin.LatinIME; -import com.android.inputmethod.latin.LatinIME.UIHandler; -import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.SuggestedWords; -import com.android.inputmethod.latin.Utils; - import android.app.AlertDialog; import android.content.ContentResolver; import android.content.Context; @@ -63,6 +46,25 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.widget.TextView; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; +import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; +import com.android.inputmethod.compat.SharedPreferencesCompat; +import com.android.inputmethod.deprecated.voice.FieldContext; +import com.android.inputmethod.deprecated.voice.Hints; +import com.android.inputmethod.deprecated.voice.SettingsUtil; +import com.android.inputmethod.deprecated.voice.VoiceInput; +import com.android.inputmethod.keyboard.KeyboardSwitcher; +import com.android.inputmethod.keyboard.LatinKeyboardView; +import com.android.inputmethod.latin.EditingUtils; +import com.android.inputmethod.latin.LastComposedWord; +import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinIME.UIHandler; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.SubtypeSwitcher; +import com.android.inputmethod.latin.Utils; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -90,6 +92,7 @@ public class VoiceProxy implements VoiceInput.UiListener { private static final boolean DEBUG = LatinImeLogger.sDBG; private boolean mAfterVoiceInput; + private boolean mConfigurationChanging; private boolean mHasUsedVoiceInput; private boolean mHasUsedVoiceInputUnsupportedLocale; private boolean mImmediatelyAfterVoiceInput; @@ -157,11 +160,11 @@ public class VoiceProxy implements VoiceInput.UiListener { mPasswordText = isPasswordText; } - public void flushVoiceInputLogs(boolean configurationChanged) { + public void flushVoiceInputLogs() { if (!VOICE_INSTALLED) { return; } - if (!configurationChanged) { + if (!mConfigurationChanging) { if (mAfterVoiceInput) { mVoiceInput.flushAllTextModificationCounters(); mVoiceInput.logInputEnded(); @@ -316,11 +319,11 @@ public class VoiceProxy implements VoiceInput.UiListener { mImmediatelyAfterVoiceInput = false; } - public void hideVoiceWindow(boolean configurationChanging) { + public void hideVoiceWindow() { if (!VOICE_INSTALLED) { return; } - if (!configurationChanging) { + if (!mConfigurationChanging) { if (mAfterVoiceInput) mVoiceInput.logInputEnded(); if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { @@ -433,44 +436,6 @@ public class VoiceProxy implements VoiceInput.UiListener { } } - /** - * Tries to apply any voice alternatives for the word if this was a spoken word and - * there are voice alternatives. - * @param touching The word that the cursor is touching, with position information - * @return true if an alternative was found, false otherwise. - */ - public boolean applyVoiceAlternatives(EditingUtils.SelectedWord touching) { - if (!VOICE_INSTALLED) { - return false; - } - // Search for result in spoken word alternatives - String selectedWord = touching.mWord.toString().trim(); - if (!mWordToSuggestions.containsKey(selectedWord)) { - selectedWord = selectedWord.toLowerCase(); - } - if (mWordToSuggestions.containsKey(selectedWord)) { - mShowingVoiceSuggestions = true; - List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord); - SuggestedWords.Builder builder = new SuggestedWords.Builder(); - // If the first letter of touching is capitalized, make all the suggestions - // start with a capital letter. - if (Character.isUpperCase(touching.mWord.charAt(0))) { - for (CharSequence word : suggestions) { - String str = word.toString(); - word = Character.toUpperCase(str.charAt(0)) + str.substring(1); - builder.addWord(word); - } - } else { - builder.addWords(suggestions, null); - } - builder.setTypedWordValid(true).setHasMinimalSuggestion(true); - mService.setSuggestions(builder.build()); -// mService.setCandidatesViewShown(true); - return true; - } - return false; - } - public void handleBackspace() { if (!VOICE_INSTALLED) { return; @@ -552,7 +517,7 @@ public class VoiceProxy implements VoiceInput.UiListener { mHints.registerVoiceResult(bestResult); if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text - mService.commitTyped(ic); + mService.commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); EditingUtils.appendText(ic, bestResult); if (ic != null) ic.endBatchEdit(); @@ -695,12 +660,12 @@ public class VoiceProxy implements VoiceInput.UiListener { && !mVoiceInput.isBlacklistedField(fieldContext); } - private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) { + private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo editorInfo) { @SuppressWarnings("deprecation") - final boolean noMic = Utils.inPrivateImeOptions(null, - LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, attribute) - || Utils.inPrivateImeOptions(mService.getPackageName(), - LatinIME.IME_OPTION_NO_MICROPHONE, attribute); + final boolean noMic = StringUtils.inPrivateImeOptions(null, + LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo) + || StringUtils.inPrivateImeOptions(mService.getPackageName(), + LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo); return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic && SpeechRecognizer.isRecognitionAvailable(mService); } @@ -709,7 +674,7 @@ public class VoiceProxy implements VoiceInput.UiListener { return SpeechRecognizer.isRecognitionAvailable(context); } - public void loadSettings(EditorInfo attribute, SharedPreferences sp) { + public void loadSettings(EditorInfo editorInfo, SharedPreferences sp) { if (!VOICE_INSTALLED) { return; } @@ -723,7 +688,7 @@ public class VoiceProxy implements VoiceInput.UiListener { final String voiceMode = sp.getString(PREF_VOICE_MODE, mService.getString(R.string.voice_mode_main)); mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off)) - && shouldShowVoiceButton(makeFieldContext(), attribute); + && shouldShowVoiceButton(makeFieldContext(), editorInfo); mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main)); } @@ -747,8 +712,9 @@ public class VoiceProxy implements VoiceInput.UiListener { // keep showing the warning. if (mSubtypeSwitcher.isVoiceMode() && windowToken != null) { // Close keyboard view if it is been shown. - if (KeyboardSwitcher.getInstance().isInputViewShown()) - KeyboardSwitcher.getInstance().getKeyboardView().purgeKeyboardAndClosing(); + final LatinKeyboardView keyboardView = KeyboardSwitcher.getInstance().getKeyboardView(); + if (keyboardView != null && keyboardView.isShown()) + keyboardView.purgeKeyboardAndClosing(); startListening(false, windowToken); } // If we have no token, onAttachedToWindow will take care of showing dialog and start @@ -877,4 +843,12 @@ public class VoiceProxy implements VoiceInput.UiListener { SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES, DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES); } + + public void startChangingConfiguration() { + mConfigurationChanging = true; + } + + public void finishChangingConfiguration() { + mConfigurationChanging = false; + } } diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java index dbe7aec6a..421ee6529 100644 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java @@ -16,16 +16,6 @@ package com.android.inputmethod.deprecated.languageswitcher; -import com.android.inputmethod.compat.SharedPreferencesCompat; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder; -import com.android.inputmethod.latin.DictionaryFactory; -import com.android.inputmethod.latin.LocaleUtils; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Settings; -import com.android.inputmethod.latin.Utils; - -import org.xmlpull.v1.XmlPullParserException; - import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Resources; @@ -37,6 +27,16 @@ import android.preference.PreferenceManager; import android.text.TextUtils; import android.util.Pair; +import com.android.inputmethod.compat.SharedPreferencesCompat; +import com.android.inputmethod.keyboard.KeyboardSet; +import com.android.inputmethod.latin.DictionaryFactory; +import com.android.inputmethod.latin.LocaleUtils; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.Settings; +import com.android.inputmethod.latin.StringUtils; + +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; import java.text.Collator; import java.util.ArrayList; @@ -162,8 +162,8 @@ public class InputLanguageSelection extends PreferenceActivity { try { final String localeStr = locale.toString(); - final String[] layoutCountryCodes = KeyboardBuilder.parseKeyboardLocale( - this, R.xml.kbd_qwerty).split(",", -1); + final String[] layoutCountryCodes = KeyboardSet.parseKeyboardLocale( + getResources(), R.xml.keyboard_set).split(",", -1); if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) { for (String s : layoutCountryCodes) { if (s.equals(localeStr)) { @@ -237,12 +237,12 @@ public class InputLanguageSelection extends PreferenceActivity { if (finalSize == 0) { preprocess[finalSize++] = - new LocaleEntry(Utils.getFullDisplayName(l, false), l); + new LocaleEntry(StringUtils.getFullDisplayName(l, false), l); } else { if (s.equals("zz_ZZ")) { // ignore this locale } else { - final String displayName = Utils.getFullDisplayName(l, false); + final String displayName = StringUtils.getFullDisplayName(l, false); preprocess[finalSize++] = new LocaleEntry(displayName, l); } } diff --git a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java index 3c79cc218..fd2cf3d25 100644 --- a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java +++ b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java @@ -43,10 +43,10 @@ public class FieldContext { Bundle mFieldInfo; - public FieldContext(InputConnection conn, EditorInfo info, + public FieldContext(InputConnection conn, EditorInfo editorInfo, String selectedLanguage, String[] enabledLanguages) { mFieldInfo = new Bundle(); - addEditorInfoToBundle(info, mFieldInfo); + addEditorInfoToBundle(editorInfo, mFieldInfo); addInputConnectionToBundle(conn, mFieldInfo); addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo); if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString()); diff --git a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java index 71d15dc3d..ff8b1abce 100644 --- a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java +++ b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java @@ -16,10 +16,6 @@ package com.android.inputmethod.deprecated.voice; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.Utils; - import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -39,6 +35,10 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.SubtypeSwitcher; + import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -222,7 +222,7 @@ public class RecognitionView { Locale locale = SubtypeSwitcher.getInstance().getInputLocale(); mLanguage.setVisibility(View.VISIBLE); - mLanguage.setText(Utils.getFullDisplayName(locale, true)); + mLanguage.setText(StringUtils.getFullDisplayName(locale, true)); mPopupLayout.setBackgroundDrawable(mListeningBorder); break; diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index f1ae0b313..b09a27540 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -22,56 +22,66 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.TextUtils; +import android.util.Log; import android.util.Xml; +import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; -import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.keyboard.internal.MoreKeySpecParser; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; /** * Class for describing the position and characteristics of a single key in the keyboard. */ public class Key { + private static final String TAG = Key.class.getSimpleName(); + /** * The key code (unicode or custom code) that this key generates. */ public final int mCode; + public final int mAltCode; /** Label to display */ - public final CharSequence mLabel; + public final String mLabel; /** Hint label to display on the key in conjunction with the label */ - public final CharSequence mHintLabel; - /** Option of the label */ - private final int mLabelOption; - private static final int LABEL_OPTION_ALIGN_LEFT = 0x01; - private static final int LABEL_OPTION_ALIGN_RIGHT = 0x02; - private static final int LABEL_OPTION_ALIGN_LEFT_OF_CENTER = 0x08; - private static final int LABEL_OPTION_LARGE_LETTER = 0x10; - private static final int LABEL_OPTION_FONT_NORMAL = 0x20; - private static final int LABEL_OPTION_FONT_MONO_SPACE = 0x40; - private static final int LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO = 0x80; - private static final int LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100; - private static final int LABEL_OPTION_HAS_POPUP_HINT = 0x200; - private static final int LABEL_OPTION_HAS_UPPERCASE_LETTER = 0x400; - private static final int LABEL_OPTION_HAS_HINT_LABEL = 0x800; - private static final int LABEL_OPTION_WITH_ICON_LEFT = 0x1000; - private static final int LABEL_OPTION_WITH_ICON_RIGHT = 0x2000; - private static final int LABEL_OPTION_AUTO_X_SCALE = 0x4000; + public final String mHintLabel; + /** Flags of the label */ + private final int mLabelFlags; + private static final int LABEL_FLAGS_ALIGN_LEFT = 0x01; + private static final int LABEL_FLAGS_ALIGN_RIGHT = 0x02; + private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08; + private static final int LABEL_FLAGS_LARGE_LETTER = 0x10; + private static final int LABEL_FLAGS_FONT_NORMAL = 0x20; + private static final int LABEL_FLAGS_FONT_MONO_SPACE = 0x40; + public static final int LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO = 0x80; + private static final int LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO = 0x100; + 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; + private static final int LABEL_FLAGS_WITH_ICON_LEFT = 0x1000; + private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000; + private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000; + private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000; + private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000; + private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x20000; + private static final int LABEL_FLAGS_DISABLE_HINT_LABEL = 0x40000000; + private static final int LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS = 0x80000000; /** Icon to display instead of a label. Icon takes precedence over a label */ - private Drawable mIcon; + private final int mIconId; + /** Icon for disabled state */ + private final int mDisabledIconId; /** Preview version of the icon, for the preview popup */ - private Drawable mPreviewIcon; + private final int mPreviewIconId; /** Width of the key, not including the gap */ public final int mWidth; @@ -94,106 +104,83 @@ public class Key { /** Text to output when pressed. This can be multiple characters, like ".com" */ public final CharSequence mOutputText; /** More keys */ - public final CharSequence[] mMoreKeys; - /** More keys maximum column number */ - public final int mMaxMoreKeysColumn; + public final String[] mMoreKeys; + /** More keys column number and flags */ + private final int mMoreKeysColumnAndFlags; + private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff; + private static final int MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER = 0x80000000; + private static final int MORE_KEYS_FLAGS_HAS_LABELS = 0x40000000; + private static final int MORE_KEYS_FLAGS_NEEDS_DIVIDERS = 0x20000000; + private static final int MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY = 0x10000000; + private static final String MORE_KEYS_AUTO_COLUMN_ORDER = "!autoColumnOrder!"; + private static final String MORE_KEYS_FIXED_COLUMN_ORDER = "!fixedColumnOrder!"; + private static final String MORE_KEYS_HAS_LABELS = "!hasLabels!"; + private static final String MORE_KEYS_NEEDS_DIVIDERS = "!needsDividers!"; + private static final String MORE_KEYS_EMBEDDED_MORE_KEY = "!embeddedMoreKey!"; /** Background type that represents different key background visual than normal one. */ public final int mBackgroundType; public static final int BACKGROUND_TYPE_NORMAL = 0; public static final int BACKGROUND_TYPE_FUNCTIONAL = 1; public static final int BACKGROUND_TYPE_ACTION = 2; - public static final int BACKGROUND_TYPE_STICKY = 3; + public static final int BACKGROUND_TYPE_STICKY_OFF = 3; + public static final int BACKGROUND_TYPE_STICKY_ON = 4; + + private final int mActionFlags; + private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01; + private static final int ACTION_FLAGS_NO_KEY_PREVIEW = 0x02; + private static final int ACTION_FLAGS_ALT_CODE_WHILE_TYPING = 0x04; + private static final int ACTION_FLAGS_ENABLE_LONG_PRESS = 0x08; - /** Whether this key repeats itself when held down */ - public final boolean mRepeatable; + private final int mHashCode; /** The current pressed state of this key */ private boolean mPressed; - /** If this is a sticky key, is its highlight on? */ - private boolean mHighlightOn; /** Key is enabled and responds on press */ private boolean mEnabled = true; - /** Whether this key needs to show the "..." popup hint for special purposes */ - private boolean mNeedsSpecialPopupHint; - - // RTL parenthesis character swapping map. - private static final Map<Integer, Integer> sRtlParenthesisMap = new HashMap<Integer, Integer>(); - - static { - // The all letters need to be mirrored are found at - // http://www.unicode.org/Public/6.0.0/ucd/extracted/DerivedBinaryProperties.txt - addRtlParenthesisPair('(', ')'); - addRtlParenthesisPair('[', ']'); - addRtlParenthesisPair('{', '}'); - addRtlParenthesisPair('<', '>'); - // \u00ab: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - // \u00bb: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - addRtlParenthesisPair('\u00ab', '\u00bb'); - // \u2039: SINGLE LEFT-POINTING ANGLE QUOTATION MARK - // \u203a: SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - addRtlParenthesisPair('\u2039', '\u203a'); - // \u2264: LESS-THAN OR EQUAL TO - // \u2265: GREATER-THAN OR EQUAL TO - addRtlParenthesisPair('\u2264', '\u2265'); - } - - private static void addRtlParenthesisPair(int left, int right) { - sRtlParenthesisMap.put(left, right); - sRtlParenthesisMap.put(right, left); - } - - public static int getRtlParenthesisCode(int code, boolean isRtl) { - if (isRtl && sRtlParenthesisMap.containsKey(code)) { - return sRtlParenthesisMap.get(code); - } else { - return code; - } - } - - private static int getCode(Resources res, KeyboardParams params, String moreKeySpec) { - return getRtlParenthesisCode( - MoreKeySpecParser.getCode(res, moreKeySpec), params.mIsRtlKeyboard); - } - - private static Drawable getIcon(KeyboardParams params, String moreKeySpec) { - return params.mIconsSet.getIcon(MoreKeySpecParser.getIconId(moreKeySpec)); - } /** * This constructor is being used only for key in more keys keyboard. */ - public Key(Resources res, KeyboardParams params, String moreKeySpec, - int x, int y, int width, int height) { - this(params, MoreKeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec), - getCode(res, params, moreKeySpec), MoreKeySpecParser.getOutputText(moreKeySpec), - x, y, width, height); + public Key(Resources res, Keyboard.Params params, String moreKeySpec, + int x, int y, int width, int height, int labelFlags) { + this(params, KeySpecParser.getLabel(moreKeySpec), null, + KeySpecParser.getIconId(moreKeySpec), + KeySpecParser.getCode(res, moreKeySpec), + KeySpecParser.getOutputText(moreKeySpec), + x, y, width, height, labelFlags); } /** * This constructor is being used only for key in popup suggestions pane. */ - public Key(KeyboardParams params, CharSequence label, CharSequence hintLabel, Drawable icon, - int code, CharSequence outputText, int x, int y, int width, int height) { + public Key(Keyboard.Params params, String label, String hintLabel, int iconId, + int code, String outputText, int x, int y, int width, int height, int labelFlags) { mHeight = height - params.mVerticalGap; mHorizontalGap = params.mHorizontalGap; mVerticalGap = params.mVerticalGap; mVisualInsetsLeft = mVisualInsetsRight = 0; mWidth = width - mHorizontalGap; mHintLabel = hintLabel; - mLabelOption = 0; + mLabelFlags = labelFlags; mBackgroundType = BACKGROUND_TYPE_NORMAL; - mRepeatable = false; + mActionFlags = 0; mMoreKeys = null; - mMaxMoreKeysColumn = 0; + mMoreKeysColumnAndFlags = 0; mLabel = label; mOutputText = outputText; mCode = code; - mIcon = icon; + mEnabled = (code != Keyboard.CODE_UNSPECIFIED); + mAltCode = Keyboard.CODE_UNSPECIFIED; + mIconId = iconId; + mDisabledIconId = KeyboardIconsSet.ICON_UNDEFINED; + mPreviewIconId = KeyboardIconsSet.ICON_UNDEFINED; // Horizontal gap is divided equally to both sides of the key. mX = x + mHorizontalGap / 2; mY = y; mHitBox.set(x, y, x + width + 1, y + height); + + mHashCode = hashCode(this); } /** @@ -205,9 +192,10 @@ public class Key { * this key. * @param parser the XML parser containing the attributes for this key * @param keyStyles active key styles set + * @throws XmlPullParserException */ - public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row, - XmlPullParser parser, KeyStyles keyStyles) { + public Key(Resources res, Keyboard.Params params, Keyboard.Builder.Row row, + XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException { final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap; final int keyHeight = row.mRowHeight; mVerticalGap = params.mVerticalGap; @@ -221,9 +209,10 @@ public class Key { String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle); style = keyStyles.getKeyStyle(styleName); if (style == null) - throw new ParseException("Unknown key style: " + styleName, parser); + throw new XmlParseUtils.ParseException( + "Unknown key style: " + styleName, parser); } else { - style = keyStyles.getEmptyKeyStyle(); + style = KeyStyles.getEmptyKeyStyle(); } final float keyXPos = row.getKeyX(keyAttr); @@ -239,89 +228,267 @@ public class Key { // Update row to have current x coordinate. row.setXPos(keyXPos + keyWidth); - final CharSequence[] moreKeys = style.getTextArray(keyAttr, - R.styleable.Keyboard_Key_moreKeys); - // In Arabic symbol layouts, we'd like to keep digits in more keys regardless of - // config_digit_more_keys_enabled. - if (params.mId.isAlphabetKeyboard() - && !res.getBoolean(R.bool.config_digit_more_keys_enabled)) { - mMoreKeys = MoreKeySpecParser.filterOut(res, moreKeys, MoreKeySpecParser.DIGIT_FILTER); - } else { - mMoreKeys = moreKeys; - } - mMaxMoreKeysColumn = style.getInt(keyAttr, - R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMiniKeyboardColumn); - mBackgroundType = style.getInt(keyAttr, R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL); - mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false); - mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true); - final KeyboardIconsSet iconsSet = params.mIconsSet; - mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr, + mVisualInsetsLeft = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr, R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0); - mVisualInsetsRight = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr, + mVisualInsetsRight = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr, R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0); - mPreviewIcon = iconsSet.getIcon(style.getInt(keyAttr, - R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED)); - mIcon = iconsSet.getIcon(style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIcon, - KeyboardIconsSet.ICON_UNDEFINED)); - final int shiftedIconId = style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted, - KeyboardIconsSet.ICON_UNDEFINED); - if (shiftedIconId != KeyboardIconsSet.ICON_UNDEFINED) { - final Drawable shiftedIcon = iconsSet.getIcon(shiftedIconId); - params.addShiftedIcon(this, shiftedIcon); + mPreviewIconId = style.getInt(keyAttr, + R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED); + mIconId = style.getInt(keyAttr, + R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED); + mDisabledIconId = style.getInt(keyAttr, + R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED); + + mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags) + | row.getDefaultKeyLabelFlags(); + final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0; + int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); + String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); + + int moreKeysColumn = style.getInt(keyAttr, + R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn); + int value; + if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) { + moreKeysColumn = value & MORE_KEYS_COLUMN_MASK; + } + if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) { + moreKeysColumn = MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER | (value & MORE_KEYS_COLUMN_MASK); } - mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); - - mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel); - mLabelOption = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption, 0); - mOutputText = style.getText(keyAttr, R.styleable.Keyboard_Key_keyOutputText); - // Choose the first letter of the label as primary code if not - // specified. - final int code = style.getInt(keyAttr, R.styleable.Keyboard_Key_code, - Keyboard.CODE_UNSPECIFIED); - if (code == Keyboard.CODE_UNSPECIFIED && !TextUtils.isEmpty(mLabel)) { - final int firstChar = mLabel.charAt(0); - mCode = getRtlParenthesisCode(firstChar, params.mIsRtlKeyboard); - } else if (code != Keyboard.CODE_UNSPECIFIED) { - mCode = code; + if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_HAS_LABELS)) { + moreKeysColumn |= MORE_KEYS_FLAGS_HAS_LABELS; + } + if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_NEEDS_DIVIDERS)) { + moreKeysColumn |= MORE_KEYS_FLAGS_NEEDS_DIVIDERS; + } + if (KeySpecParser.getBooleanValue(moreKeys, MORE_KEYS_EMBEDDED_MORE_KEY)) { + moreKeysColumn |= MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY; + } + mMoreKeysColumnAndFlags = moreKeysColumn; + + final String[] additionalMoreKeys; + if ((mLabelFlags & LABEL_FLAGS_DISABLE_ADDITIONAL_MORE_KEYS) != 0) { + additionalMoreKeys = null; } else { - mCode = Keyboard.CODE_DUMMY; + additionalMoreKeys = style.getStringArray( + keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); } + moreKeys = KeySpecParser.insertAddtionalMoreKeys(moreKeys, additionalMoreKeys); + if (moreKeys != null) { + actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS; + for (int i = 0; i < moreKeys.length; i++) { + moreKeys[i] = adjustCaseOfStringForKeyboardId( + moreKeys[i], preserveCase, params.mId); + } + } + mActionFlags = actionFlags; + mMoreKeys = moreKeys; + + if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) { + mLabel = params.mId.mCustomActionLabel; + } else { + mLabel = adjustCaseOfStringForKeyboardId(style.getString( + keyAttr, R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId); + } + if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) { + mHintLabel = null; + } else { + mHintLabel = adjustCaseOfStringForKeyboardId(style.getString( + keyAttr, R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId); + } + String outputText = adjustCaseOfStringForKeyboardId(style.getString( + keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId); + final int code = style.getInt( + keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED); + // Choose the first letter of the label as primary code if not specified. + if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) + && !TextUtils.isEmpty(mLabel)) { + if (StringUtils.codePointCount(mLabel) == 1) { + // Use the first letter of the hint label if shiftedLetterActivated flag is + // specified. + if (hasShiftedLetterHint() && isShiftedLetterActivated() + && !TextUtils.isEmpty(mHintLabel)) { + mCode = mHintLabel.codePointAt(0); + } else { + mCode = mLabel.codePointAt(0); + } + } else { + // In some locale and case, the character might be represented by multiple code + // points, such as upper case Eszett of German alphabet. + outputText = mLabel; + mCode = Keyboard.CODE_OUTPUT_TEXT; + } + } else if (code == Keyboard.CODE_UNSPECIFIED && outputText != null) { + if (StringUtils.codePointCount(outputText) == 1) { + mCode = outputText.codePointAt(0); + outputText = null; + } else { + mCode = Keyboard.CODE_OUTPUT_TEXT; + } + } else { + mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId); + } + mOutputText = outputText; + mAltCode = adjustCaseOfCodeForKeyboardId(style.getInt(keyAttr, + R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED), preserveCase, + params.mId); + mHashCode = hashCode(this); keyAttr.recycle(); + + if (hasShiftedLetterHint() && TextUtils.isEmpty(mHintLabel)) { + Log.w(TAG, "hasShiftedLetterHint specified without keyHintLabel: " + this); + } } - public void markAsLeftEdge(KeyboardParams params) { + private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase, + KeyboardId id) { + if (!Keyboard.isLetterCode(code) || preserveCase) return code; + final String text = new String(new int[] { code } , 0, 1); + final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id); + return StringUtils.codePointCount(casedText) == 1 + ? casedText.codePointAt(0) : Keyboard.CODE_UNSPECIFIED; + } + + private static String adjustCaseOfStringForKeyboardId(String text, boolean preserveCase, + KeyboardId id) { + if (text == null || preserveCase) return text; + switch (id.mElementId) { + case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED: + case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: + return text.toUpperCase(id.mLocale); + default: + return text; + } + } + + private static int hashCode(Key key) { + return Arrays.hashCode(new Object[] { + key.mX, + key.mY, + key.mWidth, + key.mHeight, + key.mCode, + key.mLabel, + key.mHintLabel, + key.mIconId, + key.mBackgroundType, + Arrays.hashCode(key.mMoreKeys), + key.mOutputText, + key.mActionFlags, + key.mLabelFlags, + // Key can be distinguishable without the following members. + // key.mAltCode, + // key.mDisabledIconId, + // key.mPreviewIconId, + // key.mHorizontalGap, + // key.mVerticalGap, + // key.mVisualInsetLeft, + // key.mVisualInsetRight, + // key.mMaxMoreKeysColumn, + }); + } + + private boolean equals(Key o) { + if (this == o) return true; + return o.mX == mX + && o.mY == mY + && o.mWidth == mWidth + && o.mHeight == mHeight + && o.mCode == mCode + && TextUtils.equals(o.mLabel, mLabel) + && TextUtils.equals(o.mHintLabel, mHintLabel) + && o.mIconId == mIconId + && o.mBackgroundType == mBackgroundType + && Arrays.equals(o.mMoreKeys, mMoreKeys) + && TextUtils.equals(o.mOutputText, mOutputText) + && o.mActionFlags == mActionFlags + && o.mLabelFlags == mLabelFlags; + } + + @Override + public int hashCode() { + return mHashCode; + } + + @Override + public boolean equals(Object o) { + return o instanceof Key && equals((Key)o); + } + + @Override + public String toString() { + return String.format("%s/%s %d,%d %dx%d %s/%s/%s", + Keyboard.printableCode(mCode), mLabel, mX, mY, mWidth, mHeight, mHintLabel, + KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType)); + } + + private static String backgroundName(int backgroundType) { + switch (backgroundType) { + case BACKGROUND_TYPE_NORMAL: return "normal"; + case BACKGROUND_TYPE_FUNCTIONAL: return "functional"; + case BACKGROUND_TYPE_ACTION: return "action"; + case BACKGROUND_TYPE_STICKY_OFF: return "stickyOff"; + case BACKGROUND_TYPE_STICKY_ON: return "stickyOn"; + default: return null; + } + } + + public void markAsLeftEdge(Keyboard.Params params) { mHitBox.left = params.mHorizontalEdgesPadding; } - public void markAsRightEdge(KeyboardParams params) { + public void markAsRightEdge(Keyboard.Params params) { mHitBox.right = params.mOccupiedWidth - params.mHorizontalEdgesPadding; } - public void markAsTopEdge(KeyboardParams params) { + public void markAsTopEdge(Keyboard.Params params) { mHitBox.top = params.mTopPadding; } - public void markAsBottomEdge(KeyboardParams params) { + public void markAsBottomEdge(Keyboard.Params params) { mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding; } - public boolean isSticky() { - return mBackgroundType == BACKGROUND_TYPE_STICKY; + public final boolean isSpacer() { + return this instanceof Spacer; + } + + public boolean isShift() { + return mCode == Keyboard.CODE_SHIFT; + } + + public boolean isModifier() { + return mCode == Keyboard.CODE_SHIFT || mCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL; } - public boolean isSpacer() { - return false; + public boolean isRepeatable() { + return (mActionFlags & ACTION_FLAGS_IS_REPEATABLE) != 0; + } + + public boolean noKeyPreview() { + return (mActionFlags & ACTION_FLAGS_NO_KEY_PREVIEW) != 0; + } + + public boolean altCodeWhileTyping() { + return (mActionFlags & ACTION_FLAGS_ALT_CODE_WHILE_TYPING) != 0; + } + + public boolean isLongPressEnabled() { + // We need not start long press timer on the key which has activated shifted letter. + return (mActionFlags & ACTION_FLAGS_ENABLE_LONG_PRESS) != 0 + && (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) == 0; } public Typeface selectTypeface(Typeface defaultTypeface) { // TODO: Handle "bold" here too? - if ((mLabelOption & LABEL_OPTION_FONT_NORMAL) != 0) { + if ((mLabelFlags & LABEL_FLAGS_FONT_NORMAL) != 0) { return Typeface.DEFAULT; - } else if ((mLabelOption & LABEL_OPTION_FONT_MONO_SPACE) != 0) { + } else if ((mLabelFlags & LABEL_FLAGS_FONT_MONO_SPACE) != 0) { return Typeface.MONOSPACE; } else { return defaultTypeface; @@ -329,13 +496,13 @@ public class Key { } public int selectTextSize(int letter, int largeLetter, int label, int hintLabel) { - if (mLabel.length() > 1 - && (mLabelOption & (LABEL_OPTION_FOLLOW_KEY_LETTER_RATIO - | LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) { + if (StringUtils.codePointCount(mLabel) > 1 + && (mLabelFlags & (LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO + | LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO)) == 0) { return label; - } else if ((mLabelOption & LABEL_OPTION_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) { + } else if ((mLabelFlags & LABEL_FLAGS_FOLLOW_KEY_HINT_LABEL_RATIO) != 0) { return hintLabel; - } else if ((mLabelOption & LABEL_OPTION_LARGE_LETTER) != 0) { + } else if ((mLabelFlags & LABEL_FLAGS_LARGE_LETTER) != 0) { return largeLetter; } else { return letter; @@ -343,63 +510,74 @@ public class Key { } public boolean isAlignLeft() { - return (mLabelOption & LABEL_OPTION_ALIGN_LEFT) != 0; + return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT) != 0; } public boolean isAlignRight() { - return (mLabelOption & LABEL_OPTION_ALIGN_RIGHT) != 0; + return (mLabelFlags & LABEL_FLAGS_ALIGN_RIGHT) != 0; } public boolean isAlignLeftOfCenter() { - return (mLabelOption & LABEL_OPTION_ALIGN_LEFT_OF_CENTER) != 0; + return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT_OF_CENTER) != 0; } public boolean hasPopupHint() { - return (mLabelOption & LABEL_OPTION_HAS_POPUP_HINT) != 0; - } - - public void setNeedsSpecialPopupHint(boolean needsSpecialPopupHint) { - mNeedsSpecialPopupHint = needsSpecialPopupHint; + return (mLabelFlags & LABEL_FLAGS_HAS_POPUP_HINT) != 0; } - public boolean needsSpecialPopupHint() { - return mNeedsSpecialPopupHint; - } - - public boolean hasUppercaseLetter() { - return (mLabelOption & LABEL_OPTION_HAS_UPPERCASE_LETTER) != 0; + public boolean hasShiftedLetterHint() { + return (mLabelFlags & LABEL_FLAGS_HAS_SHIFTED_LETTER_HINT) != 0; } public boolean hasHintLabel() { - return (mLabelOption & LABEL_OPTION_HAS_HINT_LABEL) != 0; + return (mLabelFlags & LABEL_FLAGS_HAS_HINT_LABEL) != 0; } public boolean hasLabelWithIconLeft() { - return (mLabelOption & LABEL_OPTION_WITH_ICON_LEFT) != 0; + return (mLabelFlags & LABEL_FLAGS_WITH_ICON_LEFT) != 0; } public boolean hasLabelWithIconRight() { - return (mLabelOption & LABEL_OPTION_WITH_ICON_RIGHT) != 0; + return (mLabelFlags & LABEL_FLAGS_WITH_ICON_RIGHT) != 0; } public boolean needsXScale() { - return (mLabelOption & LABEL_OPTION_AUTO_X_SCALE) != 0; + return (mLabelFlags & LABEL_FLAGS_AUTO_X_SCALE) != 0; } - public Drawable getIcon() { - return mIcon; + public boolean isShiftedLetterActivated() { + return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0; } - public Drawable getPreviewIcon() { - return mPreviewIcon; + public int getMoreKeysColumn() { + return mMoreKeysColumnAndFlags & MORE_KEYS_COLUMN_MASK; } - public void setIcon(Drawable icon) { - mIcon = icon; + public boolean isFixedColumnOrderMoreKeys() { + return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER) != 0; } - public void setPreviewIcon(Drawable icon) { - mPreviewIcon = icon; + public boolean hasLabelsInMoreKeys() { + return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_HAS_LABELS) != 0; + } + + public boolean needsDividersInMoreKeys() { + return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_NEEDS_DIVIDERS) != 0; + } + + public boolean hasEmbeddedMoreKey() { + return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY) != 0; + } + + public Drawable getIcon(KeyboardIconsSet iconSet) { + final int iconId = mEnabled ? mIconId : mDisabledIconId; + return iconSet.getIconDrawable(iconId); + } + + public Drawable getPreviewIcon(KeyboardIconsSet iconSet) { + return mPreviewIconId != KeyboardIconsSet.ICON_UNDEFINED + ? iconSet.getIconDrawable(mPreviewIconId) + : iconSet.getIconDrawable(mIconId); } /** @@ -420,10 +598,6 @@ public class Key { mPressed = false; } - public void setHighlightOn(boolean highlightOn) { - mHighlightOn = highlightOn; - } - public boolean isEnabled() { return mEnabled; } @@ -436,9 +610,9 @@ public class Key { * Detects if a point falls on this key. * @param x the x-coordinate of the point * @param y the y-coordinate of the point - * @return whether or not the point falls on the key. If the key is attached to an edge, it will - * assume that all points between the key and the edge are considered to be on the key. - * @see {@link #markAsLeftEdge(KeyboardParams)} etc. + * @return whether or not the point falls on the key. If the key is attached to an edge, it + * will assume that all points between the key and the edge are considered to be on the key. + * @see #markAsLeftEdge(Keyboard.Params) etc. */ public boolean isOnKey(int x, int y) { return mHitBox.contains(x, y); @@ -517,40 +691,32 @@ public class Key { * @see android.graphics.drawable.StateListDrawable#setState(int[]) */ public int[] getCurrentDrawableState() { - final boolean pressed = mPressed; - switch (mBackgroundType) { case BACKGROUND_TYPE_FUNCTIONAL: - return pressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL; + return mPressed ? KEY_STATE_FUNCTIONAL_PRESSED : KEY_STATE_FUNCTIONAL_NORMAL; case BACKGROUND_TYPE_ACTION: - return pressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL; - case BACKGROUND_TYPE_STICKY: - if (mHighlightOn) { - return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON; - } else { - return pressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF; - } + return mPressed ? KEY_STATE_ACTIVE_PRESSED : KEY_STATE_ACTIVE_NORMAL; + case BACKGROUND_TYPE_STICKY_OFF: + return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_OFF : KEY_STATE_NORMAL_HIGHLIGHT_OFF; + case BACKGROUND_TYPE_STICKY_ON: + return mPressed ? KEY_STATE_PRESSED_HIGHLIGHT_ON : KEY_STATE_NORMAL_HIGHLIGHT_ON; default: /* BACKGROUND_TYPE_NORMAL */ - return pressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL; + return mPressed ? KEY_STATE_PRESSED : KEY_STATE_NORMAL; } } public static class Spacer extends Key { - public Spacer(Resources res, KeyboardParams params, KeyboardBuilder.Row row, - XmlPullParser parser, KeyStyles keyStyles) { + public Spacer(Resources res, Keyboard.Params params, Keyboard.Builder.Row row, + XmlPullParser parser, KeyStyles keyStyles) throws XmlPullParserException { super(res, params, row, parser, keyStyles); } /** * This constructor is being used only for divider in more keys keyboard. */ - public Spacer(KeyboardParams params, Drawable icon, int x, int y, int width, int height) { - super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height); - } - - @Override - public boolean isSpacer() { - return true; + protected Spacer(Keyboard.Params params, int x, int y, int width, int height) { + super(params, null, null, KeyboardIconsSet.ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED, + null, x, y, width, height, 0); } } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 3298c41cf..ea3f6236a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -26,7 +26,7 @@ public class KeyDetector { private static final boolean DEBUG = false; public static final int NOT_A_CODE = -1; - public static final int NOT_A_KEY = -1; + private static final int ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE = 2; private final int mKeyHysteresisDistanceSquared; @@ -39,7 +39,7 @@ public class KeyDetector { // working area private static final int MAX_NEARBY_KEYS = 12; private final int[] mDistances = new int[MAX_NEARBY_KEYS]; - private final int[] mIndices = new int[MAX_NEARBY_KEYS]; + private final Key[] mNeighborKeys = new Key[MAX_NEARBY_KEYS]; /** * This class handles key detection. @@ -65,11 +65,11 @@ public class KeyDetector { return mKeyHysteresisDistanceSquared; } - protected int getTouchX(int x) { + public int getTouchX(int x) { return x + mCorrectionX; } - protected int getTouchY(int y) { + public int getTouchY(int y) { return y + mCorrectionY; } @@ -96,22 +96,22 @@ public class KeyDetector { } /** - * Computes maximum size of the array that can contain all nearby key indices returned by - * {@link #getKeyIndexAndNearbyCodes}. + * Computes maximum size of the array that can contain all nearby key codes returned by + * {@link #getNearbyCodes}. * - * @return Returns maximum size of the array that can contain all nearby key indices returned - * by {@link #getKeyIndexAndNearbyCodes}. + * @return Returns maximum size of the array that can contain all nearby key codes returned + * by {@link #getNearbyCodes}. */ protected int getMaxNearbyKeys() { return MAX_NEARBY_KEYS; } /** - * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes} + * Allocates array that can hold all key codes returned by {@link #getNearbyCodes} * method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}. * - * @return Allocates and returns an array that can hold all key indices returned by - * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are + * @return Allocates and returns an array that can hold all key codes returned by + * {@link #getNearbyCodes} method. All elements in the returned array are * initialized by {@link #NOT_A_CODE} value. */ public int[] newCodeArray() { @@ -122,7 +122,7 @@ public class KeyDetector { private void initializeNearbyKeys() { Arrays.fill(mDistances, Integer.MAX_VALUE); - Arrays.fill(mIndices, NOT_A_KEY); + Arrays.fill(mNeighborKeys, null); } /** @@ -130,14 +130,14 @@ public class KeyDetector { * If the distance of two keys are the same, the key which the point is on should be considered * as a closer one. * - * @param keyIndex index of the key. + * @param key the key to be inserted into the nearby keys buffer. * @param distance distance between the key's edge and user touched point. * @param isOnKey true if the point is on the key. * @return order of the key in the nearby buffer, 0 if it is the nearest key. */ - private int sortNearbyKeys(int keyIndex, int distance, boolean isOnKey) { + private int sortNearbyKeys(Key key, int distance, boolean isOnKey) { final int[] distances = mDistances; - final int[] indices = mIndices; + final Key[] neighborKeys = mNeighborKeys; for (int insertPos = 0; insertPos < distances.length; insertPos++) { final int comparingDistance = distances[insertPos]; if (distance < comparingDistance || (distance == comparingDistance && isOnKey)) { @@ -145,79 +145,147 @@ public class KeyDetector { if (nextPos < distances.length) { System.arraycopy(distances, insertPos, distances, nextPos, distances.length - nextPos); - System.arraycopy(indices, insertPos, indices, nextPos, - indices.length - nextPos); + System.arraycopy(neighborKeys, insertPos, neighborKeys, nextPos, + neighborKeys.length - nextPos); } distances[insertPos] = distance; - indices[insertPos] = keyIndex; + neighborKeys[insertPos] = key; return insertPos; } } return distances.length; } - private void getNearbyKeyCodes(final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; - final int[] indices = mIndices; + private void getNearbyKeyCodes(final int primaryCode, final int[] allCodes) { + final Key[] neighborKeys = mNeighborKeys; + final int maxCodesSize = allCodes.length; // allCodes[0] should always have the key code even if it is a non-letter key. - if (indices[0] == NOT_A_KEY) { + if (neighborKeys[0] == null) { allCodes[0] = NOT_A_CODE; return; } int numCodes = 0; - for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) { - final int index = indices[j]; - if (index == NOT_A_KEY) + for (int j = 0; j < neighborKeys.length && numCodes < maxCodesSize; j++) { + final Key key = neighborKeys[j]; + if (key == null) break; - final int code = keys.get(index).mCode; + final int code = key.mCode; // filter out a non-letter key from nearby keys if (code < Keyboard.CODE_SPACE) continue; allCodes[numCodes++] = code; } + if (maxCodesSize <= numCodes) { + return; + } + + final int code = (primaryCode == NOT_A_CODE) ? allCodes[0] : primaryCode; + if (code == NOT_A_CODE) { + return; + } + final List<Integer> additionalChars = mKeyboard.getAdditionalProximityChars().get(code); + if (additionalChars == null || additionalChars.size() == 0) { + return; + } + int currentCodesSize = numCodes; + allCodes[numCodes++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (maxCodesSize <= numCodes) { + return; + } + // TODO: This is O(N^2). Assuming additionalChars.size() is up to 4 or 5. + for (int i = 0; i < additionalChars.size(); ++i) { + final int additionalChar = additionalChars.get(i); + boolean contains = false; + for (int j = 0; j < currentCodesSize; ++j) { + if (additionalChar == allCodes[j]) { + contains = true; + break; + } + } + if (!contains) { + allCodes[numCodes++] = additionalChar; + if (maxCodesSize <= numCodes) { + return; + } + } + } } /** - * Finds all possible nearby key indices around a touch event point and returns the nearest key - * index. The algorithm to determine the nearby keys depends on the threshold set by + * Finds all possible nearby key codes around a touch event point and returns the nearest key. + * The algorithm to determine the nearby keys depends on the threshold set by * {@link #setProximityThreshold(int)} and the mode set by * {@link #setProximityCorrectionEnabled(boolean)}. * * @param x The x-coordinate of a touch point * @param y The y-coordinate of a touch point - * @param allCodes All nearby key code except functional key are returned in this array - * @return The nearest key index + * @param allCodes All nearby key codes except functional key are returned in this array */ - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; + // TODO: Move this method to native code. + public void getNearbyCodes(int x, int y, final int[] allCodes) { final int touchX = getTouchX(x); final int touchY = getTouchY(y); initializeNearbyKeys(); - int primaryIndex = NOT_A_KEY; - for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) { - final Key key = keys.get(index); + Key primaryKey = null; + for (final Key key : mKeyboard.getNearestKeys(touchX, touchY)) { final boolean isOnKey = key.isOnKey(touchX, touchY); final int distance = key.squaredDistanceToEdge(touchX, touchY); if (isOnKey || (mProximityCorrectOn && distance < mProximityThresholdSquare)) { - final int insertedPosition = sortNearbyKeys(index, distance, isOnKey); - if (insertedPosition == 0 && isOnKey) - primaryIndex = index; + final int insertedPosition = sortNearbyKeys(key, distance, isOnKey); + if (insertedPosition == 0 && isOnKey) { + primaryKey = key; + } } } - if (allCodes != null && allCodes.length > 0) { - getNearbyKeyCodes(allCodes); - if (DEBUG) { - Log.d(TAG, "x=" + x + " y=" + y - + " primary=" - + (primaryIndex == NOT_A_KEY ? "none" : keys.get(primaryIndex).mCode) - + " codes=" + Arrays.toString(allCodes)); + getNearbyKeyCodes(primaryKey != null ? primaryKey.mCode : NOT_A_CODE, allCodes); + if (DEBUG) { + Log.d(TAG, "x=" + x + " y=" + y + + " primary=" + printableCode(primaryKey) + + " codes=" + printableCodes(allCodes)); + } + } + + /** + * Detect the key whose hitbox the touch point is in. + * + * @param x The x-coordinate of a touch point + * @param y The y-coordinate of a touch point + * @return the key that the touch point hits. + */ + public Key detectHitKey(int x, int y) { + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + + for (final Key key : mKeyboard.getNearestKeys(touchX, touchY)) { + if (key.isOnKey(touchX, touchY)) { + return key; } } + return null; + } - return primaryIndex; + public static String printableCode(Key key) { + return key != null ? Keyboard.printableCode(key.mCode) : "none"; + } + + public static String printableCodes(int[] codes) { + final StringBuilder sb = new StringBuilder(); + boolean addDelimiter = false; + for (final int code : codes) { + if (code == NOT_A_CODE) break; + if (code == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + sb.append(" | "); + addDelimiter = false; + } else { + if (addDelimiter) sb.append(", "); + sb.append(Keyboard.printableCode(code)); + addDelimiter = true; + } + } + return "[" + sb + "]"; } } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 4578507fc..cdf07ed70 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -16,17 +16,34 @@ package com.android.inputmethod.keyboard; -import android.graphics.drawable.Drawable; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.util.Xml; +import android.view.InflateException; +import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; -import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.keyboard.internal.KeyboardShiftState; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.XmlParseUtils; -import java.util.Collections; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -47,7 +64,11 @@ import java.util.Set; * </pre> */ public class Keyboard { - /** Some common keys code. These should be aligned with values/keycodes.xml */ + private static final String TAG = Keyboard.class.getSimpleName(); + + /** Some common keys code. Must be positive. + * These should be aligned with values/keycodes.xml + */ public static final int CODE_ENTER = '\n'; public static final int CODE_TAB = '\t'; public static final int CODE_SPACE = ' '; @@ -62,22 +83,23 @@ public class Keyboard { public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; public static final int CODE_CLOSING_CURLY_BRACKET = '}'; public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; - public static final int CODE_DIGIT0 = '0'; - public static final int CODE_PLUS = '+'; - + private static final int MINIMUM_LETTER_CODE = CODE_TAB; - /** Special keys code. These should be aligned with values/keycodes.xml */ - public static final int CODE_DUMMY = 0; + /** Special keys code. Must be negative. + * These should be aligned with values/keycodes.xml + */ public static final int CODE_SHIFT = -1; public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; - public static final int CODE_CAPSLOCK = -3; - public static final int CODE_CANCEL = -4; - public static final int CODE_DELETE = -5; - public static final int CODE_SETTINGS = -6; - public static final int CODE_SHORTCUT = -7; - public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY = -98; + public static final int CODE_OUTPUT_TEXT = -3; + public static final int CODE_DELETE = -4; + public static final int CODE_SETTINGS = -5; + public static final int CODE_SHORTCUT = -6; + public static final int CODE_ACTION_ENTER = -7; + public static final int CODE_ACTION_NEXT = -8; + public static final int CODE_ACTION_PREVIOUS = -9; + public static final int CODE_LANGUAGE_SWITCH = -10; // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -99; + public static final int CODE_UNSPECIFIED = -11; public final KeyboardId mId; public final int mThemeId; @@ -98,159 +120,1205 @@ public class Keyboard { /** More keys keyboard template */ public final int mMoreKeysTemplate; - /** Maximum column for mini keyboard */ - public final int mMaxMiniKeyboardColumn; - - /** True if Right-To-Left keyboard */ - public final boolean mIsRtlKeyboard; + /** Maximum column for more keys keyboard */ + public final int mMaxMoreKeysKeyboardColumn; - /** List of keys and icons in this keyboard */ - public final List<Key> mKeys; - public final List<Key> mShiftKeys; - public final Set<Key> mShiftLockKeys; - public final Map<Key, Drawable> mShiftedIcons; - public final Map<Key, Drawable> mUnshiftedIcons; + /** Array of keys and icons in this keyboard */ + public final Key[] mKeys; + public final Key[] mShiftKeys; + public final Key[] mAltCodeKeysWhileTyping; public final KeyboardIconsSet mIconsSet; - private final KeyboardShiftState mShiftState = new KeyboardShiftState(); + private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>(); private final ProximityInfo mProximityInfo; - public Keyboard(KeyboardParams params) { + private final Map<Integer, List<Integer>> mAdditionalProximityChars; + + public Keyboard(Params params) { mId = params.mId; mThemeId = params.mThemeId; mOccupiedHeight = params.mOccupiedHeight; mOccupiedWidth = params.mOccupiedWidth; mMostCommonKeyHeight = params.mMostCommonKeyHeight; mMostCommonKeyWidth = params.mMostCommonKeyWidth; - mIsRtlKeyboard = params.mIsRtlKeyboard; mMoreKeysTemplate = params.mMoreKeysTemplate; - mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn; + mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn; mTopPadding = params.mTopPadding; mVerticalGap = params.mVerticalGap; - mKeys = Collections.unmodifiableList(params.mKeys); - mShiftKeys = Collections.unmodifiableList(params.mShiftKeys); - mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys); - mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons); - mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons); + mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]); + mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]); + mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray( + new Key[params.mAltCodeKeysWhileTyping.size()]); mIconsSet = params.mIconsSet; + mAdditionalProximityChars = params.mAdditionalProximityChars; - mProximityInfo = new ProximityInfo( + mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(), params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, - mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection); + mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection, + params.mAdditionalProximityChars); } public ProximityInfo getProximityInfo() { return mProximityInfo; } - public boolean hasShiftLockKey() { - return !mShiftLockKeys.isEmpty(); - } + public Key getKey(int code) { + if (code == CODE_UNSPECIFIED) { + return null; + } + final Integer keyCode = code; + if (mKeyCache.containsKey(keyCode)) { + return mKeyCache.get(keyCode); + } - public boolean setShiftLocked(boolean newShiftLockState) { - for (final Key key : mShiftLockKeys) { - // To represent "shift locked" state. The highlight is handled by background image that - // might be a StateListDrawable. - key.setHighlightOn(newShiftLockState); - // To represent "shifted" state. The key might have a shifted icon. - if (newShiftLockState && mShiftedIcons.containsKey(key)) { - key.setIcon(mShiftedIcons.get(key)); - } else { - key.setIcon(mUnshiftedIcons.get(key)); + for (final Key key : mKeys) { + if (key.mCode == code) { + mKeyCache.put(keyCode, key); + return key; } } - mShiftState.setShiftLocked(newShiftLockState); - return true; + mKeyCache.put(keyCode, null); + return null; } - public boolean isShiftLocked() { - return mShiftState.isShiftLocked(); + // TODO: Remove this method. + public boolean isShiftedOrShiftLocked() { + // Alphabet mode have unshifted, manual shifted, automatic shifted, shift locked, and + // shift lock shifted element. So that unshifed element is the only one that is NOT in + // shifted or shift locked state. + return mId.isAlphabetKeyboard() && mId.mElementId != KeyboardId.ELEMENT_ALPHABET; } - public boolean isShiftLockShifted() { - return mShiftState.isShiftLockShifted(); + public static boolean isLetterCode(int code) { + return code >= MINIMUM_LETTER_CODE; } - public boolean setShifted(boolean newShiftState) { - for (final Key key : mShiftKeys) { - if (!newShiftState && !mShiftState.isShiftLocked()) { - key.setIcon(mUnshiftedIcons.get(key)); - } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { - key.setIcon(mShiftedIcons.get(key)); + public static class Params { + public KeyboardId mId; + public int mThemeId; + + /** Total height and width of the keyboard, including the paddings and keys */ + public int mOccupiedHeight; + public int mOccupiedWidth; + + /** Base height and width of the keyboard used to calculate rows' or keys' heights and + * widths + */ + public int mBaseHeight; + public int mBaseWidth; + + public int mTopPadding; + public int mBottomPadding; + public int mHorizontalEdgesPadding; + public int mHorizontalCenterPadding; + + public int mDefaultRowHeight; + public int mDefaultKeyWidth; + public int mHorizontalGap; + public int mVerticalGap; + + public int mMoreKeysTemplate; + public int mMaxMoreKeysKeyboardColumn; + + public int GRID_WIDTH; + public int GRID_HEIGHT; + + public final HashSet<Key> mKeys = new HashSet<Key>(); + public final ArrayList<Key> mShiftKeys = new ArrayList<Key>(); + public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>(); + public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); + // TODO: Should be in Key instead of Keyboard.Params? + public final Map<Integer, List<Integer>> mAdditionalProximityChars = + new HashMap<Integer, List<Integer>>(); + + public KeyboardSet.KeysCache mKeysCache; + + public int mMostCommonKeyHeight = 0; + public int mMostCommonKeyWidth = 0; + + public final TouchPositionCorrection mTouchPositionCorrection = + new TouchPositionCorrection(); + + public static class TouchPositionCorrection { + private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3; + + public boolean mEnabled; + public float[] mXs; + public float[] mYs; + public float[] mRadii; + + public void load(String[] data) { + final int dataLength = data.length; + if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) { + if (LatinImeLogger.sDBG) + throw new RuntimeException( + "the size of touch position correction data is invalid"); + return; + } + + final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE; + mXs = new float[length]; + mYs = new float[length]; + mRadii = new float[length]; + try { + for (int i = 0; i < dataLength; ++i) { + final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE; + final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE; + final float value = Float.parseFloat(data[i]); + if (type == 0) { + mXs[index] = value; + } else if (type == 1) { + mYs[index] = value; + } else { + mRadii[index] = value; + } + } + } catch (NumberFormatException e) { + if (LatinImeLogger.sDBG) { + throw new RuntimeException( + "the number format for touch position correction data is invalid"); + } + mXs = null; + mYs = null; + mRadii = null; + } } - } - return mShiftState.setShifted(newShiftState); - } - public boolean isShiftedOrShiftLocked() { - return mShiftState.isShiftedOrShiftLocked(); - } + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } - public void setAutomaticTemporaryUpperCase() { - setShifted(true); - mShiftState.setAutomaticTemporaryUpperCase(); - } + public boolean isValid() { + return mEnabled && mXs != null && mYs != null && mRadii != null + && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0; + } + } - public boolean isAutomaticTemporaryUpperCase() { - return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase(); - } + protected void clearKeys() { + mKeys.clear(); + mShiftKeys.clear(); + clearHistogram(); + } - public boolean isManualTemporaryUpperCase() { - return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase(); - } + public void onAddKey(Key newKey) { + final Key key = (mKeysCache != null) ? mKeysCache.get(newKey) : newKey; + mKeys.add(key); + updateHistogram(key); + if (key.mCode == Keyboard.CODE_SHIFT) { + mShiftKeys.add(key); + } + if (key.altCodeWhileTyping()) { + mAltCodeKeysWhileTyping.add(key); + } + } - public boolean isManualTemporaryUpperCaseFromAuto() { - return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto(); - } + private int mMaxHeightCount = 0; + private int mMaxWidthCount = 0; + private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); + private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); - public KeyboardShiftState getKeyboardShiftState() { - return mShiftState; - } + private void clearHistogram() { + mMostCommonKeyHeight = 0; + mMaxHeightCount = 0; + mHeightHistogram.clear(); - public boolean isAlphaKeyboard() { - return mId.isAlphabetKeyboard(); - } + mMaxWidthCount = 0; + mMostCommonKeyWidth = 0; + mWidthHistogram.clear(); + } - public boolean isPhoneKeyboard() { - return mId.isPhoneKeyboard(); - } + private static int updateHistogramCounter(HashMap<Integer, Integer> histogram, + Integer key) { + final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; + histogram.put(key, count); + return count; + } - public boolean isNumberKeyboard() { - return mId.isNumberKeyboard(); - } + private void updateHistogram(Key key) { + final Integer height = key.mHeight + key.mVerticalGap; + final int heightCount = updateHistogramCounter(mHeightHistogram, height); + if (heightCount > mMaxHeightCount) { + mMaxHeightCount = heightCount; + mMostCommonKeyHeight = height; + } - public CharSequence adjustLabelCase(CharSequence label) { - if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3 - && Character.isLowerCase(label.charAt(0))) { - return label.toString().toUpperCase(mId.mLocale); + final Integer width = key.mWidth + key.mHorizontalGap; + final int widthCount = updateHistogramCounter(mWidthHistogram, width); + if (widthCount > mMaxWidthCount) { + mMaxWidthCount = widthCount; + mMostCommonKeyWidth = width; + } } - return label; } /** - * Returns the indices of the keys that are closest to the given point. + * Returns the array of the keys that are closest to the given point. * @param x the x-coordinate of the point * @param y the y-coordinate of the point - * @return the array of integer indices for the nearest keys to the given point. If the given + * @return the array of the nearest keys to the given point. If the given * point is out of range, then an array of size zero is returned. */ - public int[] getNearestKeys(int x, int y) { - return mProximityInfo.getNearestKeys(x, y); + public Key[] getNearestKeys(int x, int y) { + // Avoid dead pixels at edges of the keyboard + final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1)); + final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1)); + return mProximityInfo.getNearestKeys(adjustedX, adjustedY); + } + + public Map<Integer, List<Integer>> getAdditionalProximityChars() { + return mAdditionalProximityChars; + } + + public static String printableCode(int code) { + switch (code) { + case CODE_SHIFT: return "shift"; + case CODE_SWITCH_ALPHA_SYMBOL: return "symbol"; + case CODE_OUTPUT_TEXT: return "text"; + case CODE_DELETE: return "delete"; + case CODE_SETTINGS: return "settings"; + case CODE_SHORTCUT: return "shortcut"; + case CODE_ACTION_ENTER: return "actionEnter"; + case CODE_ACTION_NEXT: return "actionNext"; + case CODE_ACTION_PREVIOUS: return "actionPrevious"; + case CODE_UNSPECIFIED: return "unspec"; + case CODE_TAB: return "tab"; + case CODE_ENTER: return "enter"; + default: + if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code); + if (code < CODE_SPACE) return String.format("'\\u%02x'", code); + if (code < 0x100) return String.format("'%c'", code); + return String.format("'\\u%04x'", code); + } } - public static String themeName(int themeId) { - // This should be aligned with theme-*.xml resource files' themeId attribute. - switch (themeId) { - case 0: return "Basic"; - case 1: return "BasicHighContrast"; - case 5: return "IceCreamSandwich"; - case 6: return "Stone"; - case 7: return "StoneBold"; - case 8: return "GingerBread"; - default: return null; + /** + * Keyboard Building helper. + * + * This class parses Keyboard XML file and eventually build a Keyboard. + * The Keyboard XML file looks like: + * <pre> + * >!-- xml/keyboard.xml --< + * >Keyboard keyboard_attributes*< + * >!-- Keyboard Content --< + * >Row row_attributes*< + * >!-- Row Content --< + * >Key key_attributes* /< + * >Spacer horizontalGap="0.2in" /< + * >include keyboardLayout="@xml/other_keys"< + * ... + * >/Row< + * >include keyboardLayout="@xml/other_rows"< + * ... + * >/Keyboard< + * </pre> + * The XML file which is included in other file must have >merge< as root element, + * such as: + * <pre> + * >!-- xml/other_keys.xml --< + * >merge< + * >Key key_attributes* /< + * ... + * >/merge< + * </pre> + * and + * <pre> + * >!-- xml/other_rows.xml --< + * >merge< + * >Row row_attributes*< + * >Key key_attributes* /< + * >/Row< + * ... + * >/merge< + * </pre> + * You can also use switch-case-default tags to select Rows and Keys. + * <pre> + * >switch< + * >case case_attribute*< + * >!-- Any valid tags at switch position --< + * >/case< + * ... + * >default< + * >!-- Any valid tags at switch position --< + * >/default< + * >/switch< + * </pre> + * You can declare Key style and specify styles within Key tags. + * <pre> + * >switch< + * >case mode="email"< + * >key-style styleName="f1-key" parentStyle="modifier-key" + * keyLabel=".com" + * /< + * >/case< + * >case mode="url"< + * >key-style styleName="f1-key" parentStyle="modifier-key" + * keyLabel="http://" + * /< + * >/case< + * >/switch< + * ... + * >Key keyStyle="shift-key" ... /< + * </pre> + */ + + public static class Builder<KP extends Params> { + private static final String BUILDER_TAG = "Keyboard.Builder"; + private static final boolean DEBUG = false; + + // Keyboard XML Tags + private static final String TAG_KEYBOARD = "Keyboard"; + private static final String TAG_ROW = "Row"; + private static final String TAG_KEY = "Key"; + private static final String TAG_SPACER = "Spacer"; + private static final String TAG_INCLUDE = "include"; + private static final String TAG_MERGE = "merge"; + private static final String TAG_SWITCH = "switch"; + private static final String TAG_CASE = "case"; + private static final String TAG_DEFAULT = "default"; + public static final String TAG_KEY_STYLE = "key-style"; + + private static final int DEFAULT_KEYBOARD_COLUMNS = 10; + private static final int DEFAULT_KEYBOARD_ROWS = 4; + + protected final KP mParams; + protected final Context mContext; + protected final Resources mResources; + private final DisplayMetrics mDisplayMetrics; + + private int mCurrentY = 0; + private Row mCurrentRow = null; + private boolean mLeftEdge; + private boolean mTopEdge; + private Key mRightEdgeKey = null; + private final KeyStyles mKeyStyles = new KeyStyles(); + + /** + * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. + * Some of the key size defaults can be overridden per row from what the {@link Keyboard} + * defines. + */ + public static class Row { + // keyWidth enum constants + private static final int KEYWIDTH_NOT_ENUM = 0; + private static final int KEYWIDTH_FILL_RIGHT = -1; + private static final int KEYWIDTH_FILL_BOTH = -2; + + private final Params mParams; + /** Default width of a key in this row. */ + private float mDefaultKeyWidth; + /** Default height of a key in this row. */ + public final int mRowHeight; + /** Default keyLabelFlags in this row. */ + private int mDefaultKeyLabelFlags; + + private final int mCurrentY; + // Will be updated by {@link Key}'s constructor. + private float mCurrentX; + + public Row(Resources res, Params params, XmlPullParser parser, int y) { + mParams = params; + TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard); + mRowHeight = (int)Builder.getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_rowHeight, + params.mBaseHeight, params.mDefaultRowHeight); + keyboardAttr.recycle(); + TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard_Key); + mDefaultKeyWidth = Builder.getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_keyWidth, + params.mBaseWidth, params.mDefaultKeyWidth); + keyAttr.recycle(); + + mDefaultKeyLabelFlags = 0; + mCurrentY = y; + mCurrentX = 0.0f; + } + + public float getDefaultKeyWidth() { + return mDefaultKeyWidth; + } + + public void setDefaultKeyWidth(float defaultKeyWidth) { + mDefaultKeyWidth = defaultKeyWidth; + } + + public int getDefaultKeyLabelFlags() { + return mDefaultKeyLabelFlags; + } + + public void setDefaultKeyLabelFlags(int keyLabelFlags) { + mDefaultKeyLabelFlags = keyLabelFlags; + } + + public void setXPos(float keyXPos) { + mCurrentX = keyXPos; + } + + public void advanceXPos(float width) { + mCurrentX += width; + } + + public int getKeyY() { + return mCurrentY; + } + + public float getKeyX(TypedArray keyAttr) { + final int widthType = Builder.getEnumValue(keyAttr, + R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM); + if (widthType == KEYWIDTH_FILL_BOTH) { + // If keyWidth is fillBoth, the key width should start right after the nearest + // key on the left hand side. + return mCurrentX; + } + + final int keyboardRightEdge = mParams.mOccupiedWidth + - mParams.mHorizontalEdgesPadding; + if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) { + final float keyXPos = Builder.getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0); + if (keyXPos < 0) { + // If keyXPos is negative, the actual x-coordinate will be + // keyboardWidth + keyXPos. + // keyXPos shouldn't be less than mCurrentX because drawable area for this + // key starts at mCurrentX. Or, this key will overlaps the adjacent key on + // its left hand side. + return Math.max(keyXPos + keyboardRightEdge, mCurrentX); + } else { + return keyXPos + mParams.mHorizontalEdgesPadding; + } + } + return mCurrentX; + } + + public float getKeyWidth(TypedArray keyAttr) { + return getKeyWidth(keyAttr, mCurrentX); + } + + public float getKeyWidth(TypedArray keyAttr, float keyXPos) { + final int widthType = Builder.getEnumValue(keyAttr, + R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM); + switch (widthType) { + case KEYWIDTH_FILL_RIGHT: + case KEYWIDTH_FILL_BOTH: + final int keyboardRightEdge = + mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding; + // If keyWidth is fillRight, the actual key width will be determined to fill + // out the area up to the right edge of the keyboard. + // If keyWidth is fillBoth, the actual key width will be determined to fill out + // the area between the nearest key on the left hand side and the right edge of + // the keyboard. + return keyboardRightEdge - keyXPos; + default: // KEYWIDTH_NOT_ENUM + return Builder.getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_keyWidth, + mParams.mBaseWidth, mDefaultKeyWidth); + } + } + } + + public Builder(Context context, KP params) { + mContext = context; + final Resources res = context.getResources(); + mResources = res; + mDisplayMetrics = res.getDisplayMetrics(); + + mParams = params; + + setTouchPositionCorrectionData(context, params); + setAdditionalProximityChars(context, params); + + params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); + params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); + } + + private static void setTouchPositionCorrectionData(Context context, Params params) { + final TypedArray a = context.obtainStyledAttributes( + null, R.styleable.Keyboard, R.attr.keyboardStyle, 0); + params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0); + final int resourceId = a.getResourceId( + R.styleable.Keyboard_touchPositionCorrectionData, 0); + a.recycle(); + if (resourceId == 0) { + if (LatinImeLogger.sDBG) + Log.e(BUILDER_TAG, "touchPositionCorrectionData is not defined"); + return; + } + + final String[] data = context.getResources().getStringArray(resourceId); + params.mTouchPositionCorrection.load(data); + } + + private static void setAdditionalProximityChars(Context context, Params params) { + final String[] additionalChars = + context.getResources().getStringArray(R.array.additional_proximitychars); + int currentPrimaryIndex = 0; + for (int i = 0; i < additionalChars.length; ++i) { + final String additionalChar = additionalChars[i]; + if (TextUtils.isEmpty(additionalChar)) { + currentPrimaryIndex = 0; + } else if (currentPrimaryIndex == 0) { + currentPrimaryIndex = additionalChar.charAt(0); + params.mAdditionalProximityChars.put( + currentPrimaryIndex, new ArrayList<Integer>()); + } else if (currentPrimaryIndex != 0) { + final int c = additionalChar.charAt(0); + params.mAdditionalProximityChars.get(currentPrimaryIndex).add(c); + } + } + } + + public void setAutoGenerate(KeyboardSet.KeysCache keysCache) { + mParams.mKeysCache = keysCache; + } + + public Builder<KP> load(int xmlId, KeyboardId id) { + mParams.mId = id; + final XmlResourceParser parser = mResources.getXml(xmlId); + try { + parseKeyboard(parser); + } catch (XmlPullParserException e) { + Log.w(BUILDER_TAG, "keyboard XML parse error: " + e); + throw new IllegalArgumentException(e); + } catch (IOException e) { + Log.w(BUILDER_TAG, "keyboard XML parse error: " + e); + throw new RuntimeException(e); + } finally { + parser.close(); + } + return this; + } + + public void setTouchPositionCorrectionEnabled(boolean enabled) { + mParams.mTouchPositionCorrection.setEnabled(enabled); + } + + public Keyboard build() { + return new Keyboard(mParams); + } + + private int mIndent; + private static final String SPACES = " "; + + private static String spaces(int count) { + return (count < SPACES.length()) ? SPACES.substring(0, count) : SPACES; + } + + private void startTag(String format, Object ... args) { + Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args)); + } + + private void endTag(String format, Object ... args) { + Log.d(BUILDER_TAG, String.format(spaces(mIndent-- * 2) + format, args)); + } + + private void startEndTag(String format, Object ... args) { + Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args)); + mIndent--; + } + + private void parseKeyboard(XmlPullParser parser) + throws XmlPullParserException, IOException { + if (DEBUG) startTag("<%s> %s", TAG_KEYBOARD, mParams.mId); + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_KEYBOARD.equals(tag)) { + parseKeyboardAttributes(parser); + startKeyboard(); + parseKeyboardContent(parser, false); + break; + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD); + } + } + } + } + + private void parseKeyboardAttributes(XmlPullParser parser) { + final int displayWidth = mDisplayMetrics.widthPixels; + final TypedArray keyboardAttr = mContext.obtainStyledAttributes( + Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle, + R.style.Keyboard); + final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard_Key); + try { + final int displayHeight = mDisplayMetrics.heightPixels; + final int keyboardHeight = (int)keyboardAttr.getDimension( + R.styleable.Keyboard_keyboardHeight, displayHeight / 2); + final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2); + int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2); + if (minKeyboardHeight < 0) { + // Specified fraction was negative, so it should be calculated against display + // width. + minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2); + } + final Params params = mParams; + // Keyboard height will not exceed maxKeyboardHeight and will not be less than + // minKeyboardHeight. + params.mOccupiedHeight = Math.max( + Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight); + params.mOccupiedWidth = params.mId.mWidth; + params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0); + params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0); + params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_keyboardHorizontalEdgesPadding, + mParams.mOccupiedWidth, 0); + + params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2 + - params.mHorizontalCenterPadding; + params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr, + R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth, + params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS); + params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0); + params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0); + params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding + - params.mBottomPadding + params.mVerticalGap; + params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_rowHeight, params.mBaseHeight, + params.mBaseHeight / DEFAULT_KEYBOARD_ROWS); + + params.mMoreKeysTemplate = keyboardAttr.getResourceId( + R.styleable.Keyboard_moreKeysTemplate, 0); + params.mMaxMoreKeysKeyboardColumn = keyAttr.getInt( + R.styleable.Keyboard_Key_maxMoreKeysColumn, 5); + + params.mIconsSet.loadIcons(keyboardAttr); + } finally { + keyAttr.recycle(); + keyboardAttr.recycle(); + } + } + + private void parseKeyboardContent(XmlPullParser parser, boolean skip) + throws XmlPullParserException, IOException { + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_ROW.equals(tag)) { + Row row = parseRowAttributes(parser); + if (DEBUG) startTag("<%s>%s", TAG_ROW, skip ? " skipped" : ""); + if (!skip) { + startRow(row); + } + parseRowContent(parser, row, skip); + } else if (TAG_INCLUDE.equals(tag)) { + parseIncludeKeyboardContent(parser, skip); + } else if (TAG_SWITCH.equals(tag)) { + parseSwitchKeyboardContent(parser, skip); + } else if (TAG_KEY_STYLE.equals(tag)) { + parseKeyStyle(parser, skip); + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_ROW); + } + } else if (event == XmlPullParser.END_TAG) { + final String tag = parser.getName(); + if (DEBUG) endTag("</%s>", tag); + if (TAG_KEYBOARD.equals(tag)) { + endKeyboard(); + break; + } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) + || TAG_MERGE.equals(tag)) { + break; + } else { + throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW); + } + } + } + } + + private Row parseRowAttributes(XmlPullParser parser) throws XmlPullParserException { + final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard); + try { + if (a.hasValue(R.styleable.Keyboard_horizontalGap)) + throw new XmlParseUtils.IllegalAttribute(parser, "horizontalGap"); + if (a.hasValue(R.styleable.Keyboard_verticalGap)) + throw new XmlParseUtils.IllegalAttribute(parser, "verticalGap"); + return new Row(mResources, mParams, parser, mCurrentY); + } finally { + a.recycle(); + } + } + + private void parseRowContent(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_KEY.equals(tag)) { + parseKey(parser, row, skip); + } else if (TAG_SPACER.equals(tag)) { + parseSpacer(parser, row, skip); + } else if (TAG_INCLUDE.equals(tag)) { + parseIncludeRowContent(parser, row, skip); + } else if (TAG_SWITCH.equals(tag)) { + parseSwitchRowContent(parser, row, skip); + } else if (TAG_KEY_STYLE.equals(tag)) { + parseKeyStyle(parser, skip); + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY); + } + } else if (event == XmlPullParser.END_TAG) { + final String tag = parser.getName(); + if (DEBUG) endTag("</%s>", tag); + if (TAG_ROW.equals(tag)) { + if (!skip) { + endRow(row); + } + break; + } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) + || TAG_MERGE.equals(tag)) { + break; + } else { + throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY); + } + } + } + } + + private void parseKey(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (skip) { + XmlParseUtils.checkEndTag(TAG_KEY, parser); + if (DEBUG) startEndTag("<%s /> skipped", TAG_KEY); + } else { + final Key key = new Key(mResources, mParams, row, parser, mKeyStyles); + if (DEBUG) { + startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY, + (key.isEnabled() ? "" : " disabled"), key, + Arrays.toString(key.mMoreKeys)); + } + XmlParseUtils.checkEndTag(TAG_KEY, parser); + endKey(key); + } + } + + private void parseSpacer(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (skip) { + XmlParseUtils.checkEndTag(TAG_SPACER, parser); + if (DEBUG) startEndTag("<%s /> skipped", TAG_SPACER); + } else { + final Key.Spacer spacer = new Key.Spacer( + mResources, mParams, row, parser, mKeyStyles); + if (DEBUG) startEndTag("<%s />", TAG_SPACER); + XmlParseUtils.checkEndTag(TAG_SPACER, parser); + endKey(spacer); + } + } + + private void parseIncludeKeyboardContent(XmlPullParser parser, boolean skip) + throws XmlPullParserException, IOException { + parseIncludeInternal(parser, null, skip); + } + + private void parseIncludeRowContent(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + parseIncludeInternal(parser, row, skip); + } + + private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (skip) { + XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); + if (DEBUG) startEndTag("</%s> skipped", TAG_INCLUDE); + } else { + final AttributeSet attr = Xml.asAttributeSet(parser); + final TypedArray keyboardAttr = mResources.obtainAttributes(attr, + R.styleable.Keyboard_Include); + final TypedArray keyAttr = mResources.obtainAttributes(attr, + R.styleable.Keyboard_Key); + int keyboardLayout = 0; + float savedDefaultKeyWidth = 0; + int savedDefaultKeyLabelFlags = 0; + try { + XmlParseUtils.checkAttributeExists(keyboardAttr, + R.styleable.Keyboard_Include_keyboardLayout, "keyboardLayout", + TAG_INCLUDE, parser); + keyboardLayout = keyboardAttr.getResourceId( + R.styleable.Keyboard_Include_keyboardLayout, 0); + if (row != null) { + savedDefaultKeyWidth = row.getDefaultKeyWidth(); + savedDefaultKeyLabelFlags = row.getDefaultKeyLabelFlags(); + if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) { + // Override current x coordinate. + row.setXPos(row.getKeyX(keyAttr)); + } + if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyWidth)) { + // Override default key width. + row.setDefaultKeyWidth(row.getKeyWidth(keyAttr)); + } + if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyLabelFlags)) { + // Override default key label flags. + row.setDefaultKeyLabelFlags( + keyAttr.getInt(R.styleable.Keyboard_Key_keyLabelFlags, 0) + | savedDefaultKeyLabelFlags); + } + } + } finally { + keyboardAttr.recycle(); + keyAttr.recycle(); + } + + XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); + if (DEBUG) { + startEndTag("<%s keyboardLayout=%s />",TAG_INCLUDE, + mResources.getResourceEntryName(keyboardLayout)); + } + final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout); + try { + parseMerge(parserForInclude, row, skip); + } finally { + if (row != null) { + // Restore default key width and key label flags. + row.setDefaultKeyWidth(savedDefaultKeyWidth); + row.setDefaultKeyLabelFlags(savedDefaultKeyLabelFlags); + } + parserForInclude.close(); + } + } + } + + private void parseMerge(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (DEBUG) startTag("<%s>", TAG_MERGE); + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_MERGE.equals(tag)) { + if (row == null) { + parseKeyboardContent(parser, skip); + } else { + parseRowContent(parser, row, skip); + } + break; + } else { + throw new XmlParseUtils.ParseException( + "Included keyboard layout must have <merge> root element", parser); + } + } + } + } + + private void parseSwitchKeyboardContent(XmlPullParser parser, boolean skip) + throws XmlPullParserException, IOException { + parseSwitchInternal(parser, null, skip); + } + + private void parseSwitchRowContent(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + parseSwitchInternal(parser, row, skip); + } + + private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (DEBUG) startTag("<%s> %s", TAG_SWITCH, mParams.mId); + boolean selected = false; + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_CASE.equals(tag)) { + selected |= parseCase(parser, row, selected ? true : skip); + } else if (TAG_DEFAULT.equals(tag)) { + selected |= parseDefault(parser, row, selected ? true : skip); + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEY); + } + } else if (event == XmlPullParser.END_TAG) { + final String tag = parser.getName(); + if (TAG_SWITCH.equals(tag)) { + if (DEBUG) endTag("</%s>", TAG_SWITCH); + break; + } else { + throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY); + } + } + } + } + + private boolean parseCase(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + final boolean selected = parseCaseCondition(parser); + if (row == null) { + // Processing Rows. + parseKeyboardContent(parser, selected ? skip : true); + } else { + // Processing Keys. + parseRowContent(parser, row, selected ? skip : true); + } + return selected; + } + + private boolean parseCaseCondition(XmlPullParser parser) { + final KeyboardId id = mParams.mId; + if (id == null) + return true; + + final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard_Case); + try { + final boolean keyboardSetElementMatched = matchTypedValue(a, + R.styleable.Keyboard_Case_keyboardSetElement, id.mElementId, + KeyboardId.elementIdToName(id.mElementId)); + final boolean modeMatched = matchTypedValue(a, + R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode)); + final boolean navigateNextMatched = matchBoolean(a, + R.styleable.Keyboard_Case_navigateNext, id.navigateNext()); + final boolean navigatePreviousMatched = matchBoolean(a, + R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious()); + final boolean passwordInputMatched = matchBoolean(a, + R.styleable.Keyboard_Case_passwordInput, id.passwordInput()); + final boolean clobberSettingsKeyMatched = matchBoolean(a, + R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey); + final boolean shortcutKeyEnabledMatched = matchBoolean(a, + R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled); + final boolean hasShortcutKeyMatched = matchBoolean(a, + R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey); + final boolean languageSwitchKeyEnabledMatched = matchBoolean(a, + R.styleable.Keyboard_Case_languageSwitchKeyEnabled, + id.mLanguageSwitchKeyEnabled); + final boolean isMultiLineMatched = matchBoolean(a, + R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine()); + final boolean imeActionMatched = matchInteger(a, + R.styleable.Keyboard_Case_imeAction, id.imeAction()); + final boolean localeCodeMatched = matchString(a, + R.styleable.Keyboard_Case_localeCode, id.mLocale.toString()); + final boolean languageCodeMatched = matchString(a, + R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage()); + final boolean countryCodeMatched = matchString(a, + R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry()); + final boolean selected = keyboardSetElementMatched && modeMatched + && navigateNextMatched && navigatePreviousMatched && passwordInputMatched + && clobberSettingsKeyMatched && shortcutKeyEnabledMatched + && hasShortcutKeyMatched && languageSwitchKeyEnabledMatched + && isMultiLineMatched && imeActionMatched && localeCodeMatched + && languageCodeMatched && countryCodeMatched; + + if (DEBUG) { + startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, + textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement), + "keyboardSetElement"), + textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"), + textAttr(a.getString(R.styleable.Keyboard_Case_imeAction), + "imeAction"), + booleanAttr(a, R.styleable.Keyboard_Case_navigateNext, + "navigateNext"), + booleanAttr(a, R.styleable.Keyboard_Case_navigatePrevious, + "navigatePrevious"), + booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey, + "clobberSettingsKey"), + booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, + "passwordInput"), + booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled, + "shortcutKeyEnabled"), + booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, + "hasShortcutKey"), + booleanAttr(a, R.styleable.Keyboard_Case_languageSwitchKeyEnabled, + "languageSwitchKeyEnabled"), + booleanAttr(a, R.styleable.Keyboard_Case_isMultiLine, + "isMultiLine"), + textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), + "localeCode"), + textAttr(a.getString(R.styleable.Keyboard_Case_languageCode), + "languageCode"), + textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), + "countryCode"), + selected ? "" : " skipped"); + } + + return selected; + } finally { + a.recycle(); + } + } + + private static boolean matchInteger(TypedArray a, int index, int value) { + // If <case> does not have "index" attribute, that means this <case> is wild-card for + // the attribute. + return !a.hasValue(index) || a.getInt(index, 0) == value; + } + + private static boolean matchBoolean(TypedArray a, int index, boolean value) { + // If <case> does not have "index" attribute, that means this <case> is wild-card for + // the attribute. + return !a.hasValue(index) || a.getBoolean(index, false) == value; + } + + private static boolean matchString(TypedArray a, int index, String value) { + // If <case> does not have "index" attribute, that means this <case> is wild-card for + // the attribute. + return !a.hasValue(index) + || stringArrayContains(a.getString(index).split("\\|"), value); + } + + private static boolean matchTypedValue(TypedArray a, int index, int intValue, + String strValue) { + // If <case> does not have "index" attribute, that means this <case> is wild-card for + // the attribute. + final TypedValue v = a.peekValue(index); + if (v == null) + return true; + + if (isIntegerValue(v)) { + return intValue == a.getInt(index, 0); + } else if (isStringValue(v)) { + return stringArrayContains(a.getString(index).split("\\|"), strValue); + } + return false; + } + + private static boolean stringArrayContains(String[] array, String value) { + for (final String elem : array) { + if (elem.equals(value)) + return true; + } + return false; + } + + private boolean parseDefault(XmlPullParser parser, Row row, boolean skip) + throws XmlPullParserException, IOException { + if (DEBUG) startTag("<%s>", TAG_DEFAULT); + if (row == null) { + parseKeyboardContent(parser, skip); + } else { + parseRowContent(parser, row, skip); + } + return true; + } + + private void parseKeyStyle(XmlPullParser parser, boolean skip) + throws XmlPullParserException, IOException { + TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard_KeyStyle); + TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.Keyboard_Key); + try { + if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName)) + throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE + + "/> needs styleName attribute", parser); + if (DEBUG) { + startEndTag("<%s styleName=%s />%s", TAG_KEY_STYLE, + keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName), + skip ? " skipped" : ""); + } + if (!skip) + mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser); + } finally { + keyStyleAttr.recycle(); + keyAttrs.recycle(); + } + XmlParseUtils.checkEndTag(TAG_KEY_STYLE, parser); + } + + private void startKeyboard() { + mCurrentY += mParams.mTopPadding; + mTopEdge = true; + } + + private void startRow(Row row) { + addEdgeSpace(mParams.mHorizontalEdgesPadding, row); + mCurrentRow = row; + mLeftEdge = true; + mRightEdgeKey = null; + } + + private void endRow(Row row) { + if (mCurrentRow == null) + throw new InflateException("orphant end row tag"); + if (mRightEdgeKey != null) { + mRightEdgeKey.markAsRightEdge(mParams); + mRightEdgeKey = null; + } + addEdgeSpace(mParams.mHorizontalEdgesPadding, row); + mCurrentY += row.mRowHeight; + mCurrentRow = null; + mTopEdge = false; + } + + private void endKey(Key key) { + mParams.onAddKey(key); + if (mLeftEdge) { + key.markAsLeftEdge(mParams); + mLeftEdge = false; + } + if (mTopEdge) { + key.markAsTopEdge(mParams); + } + mRightEdgeKey = key; + } + + private void endKeyboard() { + // nothing to do here. + } + + private void addEdgeSpace(float width, Row row) { + row.advanceXPos(width); + mLeftEdge = false; + mRightEdgeKey = null; + } + + public static float getDimensionOrFraction(TypedArray a, int index, int base, + float defValue) { + final TypedValue value = a.peekValue(index); + if (value == null) + return defValue; + if (isFractionValue(value)) { + return a.getFraction(index, base, base, defValue); + } else if (isDimensionValue(value)) { + return a.getDimension(index, defValue); + } + return defValue; + } + + public static int getEnumValue(TypedArray a, int index, int defValue) { + final TypedValue value = a.peekValue(index); + if (value == null) + return defValue; + if (isIntegerValue(value)) { + return a.getInt(index, defValue); + } + return defValue; + } + + private static boolean isFractionValue(TypedValue v) { + return v.type == TypedValue.TYPE_FRACTION; + } + + private static boolean isDimensionValue(TypedValue v) { + return v.type == TypedValue.TYPE_DIMENSION; + } + + private static boolean isIntegerValue(TypedValue v) { + return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT; + } + + private static boolean isStringValue(TypedValue v) { + return v.type == TypedValue.TYPE_STRING; + } + + private static String textAttr(String value, String name) { + return value != null ? String.format(" %s=%s", name, value) : ""; + } + + private static String booleanAttr(TypedArray a, int index, String name) { + return a.hasValue(index) + ? String.format(" %s=%s", name, a.getBoolean(index, false)) : ""; } } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java index 6f5420882..16b4eafc9 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java @@ -24,10 +24,8 @@ public interface KeyboardActionListener { * * @param primaryCode the unicode of the key being pressed. If the touch is not on a valid key, * the value will be zero. - * @param withSliding true if pressing has occurred because the user slid finger from other key - * to this key without releasing the finger. */ - public void onPress(int primaryCode, boolean withSliding); + public void onPressKey(int primaryCode); /** * Called when the user releases a key. This is sent after the {@link #onCodeInput} is called. @@ -37,27 +35,26 @@ public interface KeyboardActionListener { * @param withSliding true if releasing has occurred because the user slid finger from the key * to other key without releasing the finger. */ - public void onRelease(int primaryCode, boolean withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding); /** * Send a key code to the listener. * * @param primaryCode this is the code of the key that was pressed - * @param keyCodes the codes for all the possible alternative keys with the primary code being - * the first. If the primary key code is a single character such as an alphabet or - * number or symbol, the alternatives will include other characters that may be on - * the same key or adjacent keys. These codes are useful to correct for accidental - * presses of a key adjacent to the intended key. * @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by * {@link PointerTracker#onTouchEvent} or so, the value should be - * {@link #NOT_A_TOUCH_COORDINATE}. + * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion + * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}. * @param y y-coordinate pixel of touched event. If {@link #onCodeInput} is not called by * {@link PointerTracker#onTouchEvent} or so, the value should be - * {@link #NOT_A_TOUCH_COORDINATE}. + * {@link #NOT_A_TOUCH_COORDINATE}. If it's called on insertion from the suggestion + * strip, it should be {@link #SUGGESTION_STRIP_COORDINATE}. */ - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y); + public void onCodeInput(int primaryCode, int x, int y); public static final int NOT_A_TOUCH_COORDINATE = -1; + public static final int SUGGESTION_STRIP_COORDINATE = -2; + public static final int SPELL_CHECKER_COORDINATE = -3; /** * Sends a sequence of characters to the listener. @@ -79,11 +76,11 @@ public interface KeyboardActionListener { public static class Adapter implements KeyboardActionListener { @Override - public void onPress(int primaryCode, boolean withSliding) {} + public void onPressKey(int primaryCode) {} @Override - public void onRelease(int primaryCode, boolean withSliding) {} + public void onReleaseKey(int primaryCode, boolean withSliding) {} @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {} + public void onCodeInput(int primaryCode, int x, int y) {} @Override public void onTextInput(CharSequence text) {} @Override diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index 2e4988fb0..6703b9301 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -16,18 +16,18 @@ package com.android.inputmethod.keyboard; +import android.text.InputType; +import android.text.TextUtils; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.latin.R; import java.util.Arrays; import java.util.Locale; /** - * Represents the parameters necessary to construct a new LatinKeyboard, - * which also serve as a unique identifier for each keyboard type. + * Unique identifier for each keyboard type. */ public class KeyboardId { public static final int MODE_TEXT = 0; @@ -36,105 +36,132 @@ public class KeyboardId { public static final int MODE_IM = 3; public static final int MODE_PHONE = 4; public static final int MODE_NUMBER = 5; - - public static final int F2KEY_MODE_NONE = 0; - public static final int F2KEY_MODE_SETTINGS = 1; - public static final int F2KEY_MODE_SHORTCUT_IME = 2; - public static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3; + public static final int MODE_DATE = 6; + public static final int MODE_TIME = 7; + public static final int MODE_DATETIME = 8; + + public static final int ELEMENT_ALPHABET = 0; + public static final int ELEMENT_ALPHABET_MANUAL_SHIFTED = 1; + public static final int ELEMENT_ALPHABET_AUTOMATIC_SHIFTED = 2; + public static final int ELEMENT_ALPHABET_SHIFT_LOCKED = 3; + public static final int ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED = 4; + public static final int ELEMENT_SYMBOLS = 5; + public static final int ELEMENT_SYMBOLS_SHIFTED = 6; + public static final int ELEMENT_PHONE = 7; + public static final int ELEMENT_PHONE_SYMBOLS = 8; + public static final int ELEMENT_NUMBER = 9; + + private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1; public final Locale mLocale; public final int mOrientation; public final int mWidth; public final int mMode; - public final int mXmlId; - public final boolean mNavigateAction; - public final boolean mPasswordInput; - // TODO: Clean up these booleans and modes. - public final boolean mHasSettingsKey; - public final int mF2KeyMode; + public final int mElementId; + private final EditorInfo mEditorInfo; public final boolean mClobberSettingsKey; public final boolean mShortcutKeyEnabled; public final boolean mHasShortcutKey; - public final int mImeAction; - - public final String mXmlName; - public final EditorInfo mAttribute; + public final boolean mLanguageSwitchKeyEnabled; + public final String mCustomActionLabel; private final int mHashCode; - public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int width, - int mode, EditorInfo attribute, boolean hasSettingsKey, int f2KeyMode, - boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) { - final int inputType = (attribute != null) ? attribute.inputType : 0; - final int imeOptions = (attribute != null) ? attribute.imeOptions : 0; + public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, + EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, + boolean hasShortcutKey, boolean languageSwitchKeyEnabled) { this.mLocale = locale; this.mOrientation = orientation; this.mWidth = width; this.mMode = mode; - this.mXmlId = xmlId; - // Note: Turn off checking navigation flag to show TAB key for now. - this.mNavigateAction = InputTypeCompatUtils.isWebInputType(inputType); -// || EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) -// || EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions); - this.mPasswordInput = InputTypeCompatUtils.isPasswordInputType(inputType) - || InputTypeCompatUtils.isVisiblePasswordInputType(inputType); - this.mHasSettingsKey = hasSettingsKey; - this.mF2KeyMode = f2KeyMode; + this.mElementId = elementId; + this.mEditorInfo = editorInfo; this.mClobberSettingsKey = clobberSettingsKey; this.mShortcutKeyEnabled = shortcutKeyEnabled; this.mHasShortcutKey = hasShortcutKey; - // We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and - // {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}. - this.mImeAction = imeOptions & ( - EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); - - this.mXmlName = xmlName; - this.mAttribute = attribute; - - this.mHashCode = Arrays.hashCode(new Object[] { - locale, - orientation, - width, - mode, - xmlId, - mNavigateAction, - mPasswordInput, - hasSettingsKey, - f2KeyMode, - clobberSettingsKey, - shortcutKeyEnabled, - hasShortcutKey, - mImeAction, - }); + this.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; + this.mCustomActionLabel = (editorInfo.actionLabel != null) + ? editorInfo.actionLabel.toString() : null; + + this.mHashCode = hashCode(this); } - public KeyboardId cloneWithNewXml(String xmlName, int xmlId) { - return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mAttribute, - false, F2KEY_MODE_NONE, false, false, false); + private static int hashCode(KeyboardId id) { + return Arrays.hashCode(new Object[] { + id.mOrientation, + id.mElementId, + id.mMode, + id.mWidth, + id.passwordInput(), + id.mClobberSettingsKey, + id.mShortcutKeyEnabled, + id.mHasShortcutKey, + id.mLanguageSwitchKeyEnabled, + id.isMultiLine(), + id.imeAction(), + id.mCustomActionLabel, + id.navigateNext(), + id.navigatePrevious(), + id.mLocale + }); } - public int getXmlId() { - return mXmlId; + private boolean equals(KeyboardId other) { + if (other == this) + return true; + return other.mOrientation == this.mOrientation + && other.mElementId == this.mElementId + && other.mMode == this.mMode + && other.mWidth == this.mWidth + && other.passwordInput() == this.passwordInput() + && other.mClobberSettingsKey == this.mClobberSettingsKey + && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled + && other.mHasShortcutKey == this.mHasShortcutKey + && other.mLanguageSwitchKeyEnabled == this.mLanguageSwitchKeyEnabled + && other.isMultiLine() == this.isMultiLine() + && other.imeAction() == this.imeAction() + && TextUtils.equals(other.mCustomActionLabel, this.mCustomActionLabel) + && other.navigateNext() == this.navigateNext() + && other.navigatePrevious() == this.navigatePrevious() + && other.mLocale.equals(this.mLocale); } public boolean isAlphabetKeyboard() { - return mXmlId == R.xml.kbd_qwerty; + return mElementId < ELEMENT_SYMBOLS; + } + + public boolean navigateNext() { + return EditorInfoCompatUtils.hasFlagNavigateNext(mEditorInfo.imeOptions); } - public boolean isSymbolsKeyboard() { - return mXmlId == R.xml.kbd_symbols || mXmlId == R.xml.kbd_symbols_shift; + public boolean navigatePrevious() { + return EditorInfoCompatUtils.hasFlagNavigatePrevious(mEditorInfo.imeOptions); + } + + public boolean passwordInput() { + final int inputType = mEditorInfo.inputType; + return InputTypeCompatUtils.isPasswordInputType(inputType) + || InputTypeCompatUtils.isVisiblePasswordInputType(inputType); } - public boolean isPhoneKeyboard() { - return mMode == MODE_PHONE; + public boolean isMultiLine() { + return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0; } - public boolean isPhoneShiftKeyboard() { - return mXmlId == R.xml.kbd_phone_shift; + public int imeAction() { + final int actionId = mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION; + if ((mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { + return EditorInfo.IME_ACTION_NONE; + } else if (mEditorInfo.actionLabel != null) { + return IME_ACTION_CUSTOM_LABEL; + } else { + return actionId; + } } - public boolean isNumberKeyboard() { - return mMode == MODE_NUMBER; + public int imeActionId() { + final int actionId = imeAction(); + return actionId == IME_ACTION_CUSTOM_LABEL ? mEditorInfo.actionId : actionId; } @Override @@ -142,22 +169,6 @@ public class KeyboardId { return other instanceof KeyboardId && equals((KeyboardId) other); } - private boolean equals(KeyboardId other) { - return other.mLocale.equals(this.mLocale) - && other.mOrientation == this.mOrientation - && other.mWidth == this.mWidth - && other.mMode == this.mMode - && other.mXmlId == this.mXmlId - && other.mNavigateAction == this.mNavigateAction - && other.mPasswordInput == this.mPasswordInput - && other.mHasSettingsKey == this.mHasSettingsKey - && other.mF2KeyMode == this.mF2KeyMode - && other.mClobberSettingsKey == this.mClobberSettingsKey - && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled - && other.mHasShortcutKey == this.mHasShortcutKey - && other.mImeAction == this.mImeAction; - } - @Override public int hashCode() { return mHashCode; @@ -165,22 +176,47 @@ public class KeyboardId { @Override public String toString() { - return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s%s]", - mXmlName, + return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s%s]", + elementIdToName(mElementId), mLocale, (mOrientation == 1 ? "port" : "land"), mWidth, modeName(mMode), - EditorInfoCompatUtils.imeOptionsName(mImeAction), - f2KeyModeName(mF2KeyMode), + imeAction(), + (navigateNext() ? "navigateNext" : ""), + (navigatePrevious() ? "navigatePrevious" : ""), (mClobberSettingsKey ? " clobberSettingsKey" : ""), - (mNavigateAction ? " navigateAction" : ""), - (mPasswordInput ? " passwordInput" : ""), - (mHasSettingsKey ? " hasSettingsKey" : ""), + (passwordInput() ? " passwordInput" : ""), (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""), - (mHasShortcutKey ? " hasShortcutKey" : "") + (mHasShortcutKey ? " hasShortcutKey" : ""), + (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""), + (isMultiLine() ? "isMultiLine" : "") ); } + public static boolean equivalentEditorInfoForKeyboard(EditorInfo a, EditorInfo b) { + if (a == null && b == null) return true; + if (a == null || b == null) return false; + return a.inputType == b.inputType + && a.imeOptions == b.imeOptions + && TextUtils.equals(a.privateImeOptions, b.privateImeOptions); + } + + public static String elementIdToName(int elementId) { + switch (elementId) { + case ELEMENT_ALPHABET: return "alphabet"; + case ELEMENT_ALPHABET_MANUAL_SHIFTED: return "alphabetManualShifted"; + case ELEMENT_ALPHABET_AUTOMATIC_SHIFTED: return "alphabetAutomaticShifted"; + case ELEMENT_ALPHABET_SHIFT_LOCKED: return "alphabetShiftLocked"; + case ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED: return "alphabetShiftLockShifted"; + case ELEMENT_SYMBOLS: return "symbols"; + case ELEMENT_SYMBOLS_SHIFTED: return "symbolsShifted"; + case ELEMENT_PHONE: return "phone"; + case ELEMENT_PHONE_SYMBOLS: return "phoneSymbols"; + case ELEMENT_NUMBER: return "number"; + default: return null; + } + } + public static String modeName(int mode) { switch (mode) { case MODE_TEXT: return "text"; @@ -189,17 +225,15 @@ public class KeyboardId { case MODE_IM: return "im"; case MODE_PHONE: return "phone"; case MODE_NUMBER: return "number"; + case MODE_DATE: return "date"; + case MODE_TIME: return "time"; + case MODE_DATETIME: return "datetime"; default: return null; } } - public static String f2KeyModeName(int f2KeyMode) { - switch (f2KeyMode) { - case F2KEY_MODE_NONE: return "none"; - case F2KEY_MODE_SETTINGS: return "settings"; - case F2KEY_MODE_SHORTCUT_IME: return "shortcutIme"; - case F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS: return "shortcutImeOrSettings"; - default: return null; - } + public static String actionName(int actionId) { + return (actionId == IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel" + : EditorInfoCompatUtils.imeActionName(actionId); } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java new file mode 100644 index 000000000..680ff0d25 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2011 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.keyboard; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.text.InputType; +import android.util.Log; +import android.util.Xml; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.compat.EditorInfoCompatUtils; +import com.android.inputmethod.compat.InputTypeCompatUtils; +import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.LocaleUtils; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.XmlParseUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * This class represents a set of keyboards. Each of them represents a different keyboard + * specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same + * {@link KeyboardSet} are related to each other. + * A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}. + */ +public class KeyboardSet { + private static final String TAG = KeyboardSet.class.getSimpleName(); + private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; + + private static final String TAG_KEYBOARD_SET = TAG; + private static final String TAG_ELEMENT = "Element"; + + private final Context mContext; + private final Params mParams; + + private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache = + new HashMap<KeyboardId, SoftReference<Keyboard>>(); + private static final KeysCache sKeysCache = new KeysCache(); + + private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo(); + + public static class KeyboardSetException extends RuntimeException { + public final KeyboardId mKeyboardId; + public KeyboardSetException(Throwable cause, KeyboardId keyboardId) { + super(cause); + mKeyboardId = keyboardId; + } + } + + public static class KeysCache { + private final Map<Key, Key> mMap; + + public KeysCache() { + mMap = new HashMap<Key, Key>(); + } + + public void clear() { + mMap.clear(); + } + + public Key get(Key key) { + final Key existingKey = mMap.get(key); + if (existingKey != null) { + // Reuse the existing element that equals to "key" without adding "key" to the map. + return existingKey; + } + mMap.put(key, key); + return key; + } + } + + static class Params { + int mMode; + EditorInfo mEditorInfo; + boolean mTouchPositionCorrectionEnabled; + boolean mVoiceKeyEnabled; + boolean mVoiceKeyOnMain; + boolean mNoSettingsKey; + boolean mLanguageSwitchKeyEnabled; + Locale mLocale; + int mOrientation; + int mWidth; + // KeyboardSet element id to keyboard layout XML id map. + final Map<Integer, Integer> mKeyboardSetElementIdToXmlIdMap = + new HashMap<Integer, Integer>(); + Params() {} + } + + public static void clearKeyboardCache() { + sKeyboardCache.clear(); + sKeysCache.clear(); + } + + private KeyboardSet(Context context, Params params) { + mContext = context; + mParams = params; + } + + public Keyboard getKeyboard(int baseKeyboardSetElementId) { + final int keyboardSetElementId; + switch (mParams.mMode) { + case KeyboardId.MODE_PHONE: + if (baseKeyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS) { + keyboardSetElementId = KeyboardId.ELEMENT_PHONE_SYMBOLS; + } else { + keyboardSetElementId = KeyboardId.ELEMENT_PHONE; + } + break; + case KeyboardId.MODE_NUMBER: + case KeyboardId.MODE_DATE: + case KeyboardId.MODE_TIME: + case KeyboardId.MODE_DATETIME: + keyboardSetElementId = KeyboardId.ELEMENT_NUMBER; + break; + default: + keyboardSetElementId = baseKeyboardSetElementId; + break; + } + + Integer keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get(keyboardSetElementId); + if (keyboardXmlId == null) { + keyboardXmlId = mParams.mKeyboardSetElementIdToXmlIdMap.get( + KeyboardId.ELEMENT_ALPHABET); + } + final KeyboardId id = getKeyboardId(keyboardSetElementId); + try { + return getKeyboard(mContext, keyboardXmlId, id); + } catch (RuntimeException e) { + throw new KeyboardSetException(e, id); + } + } + + private Keyboard getKeyboard(Context context, int keyboardXmlId, KeyboardId id) { + final Resources res = context.getResources(); + final SoftReference<Keyboard> ref = sKeyboardCache.get(id); + Keyboard keyboard = (ref == null) ? null : ref.get(); + if (keyboard == null) { + final Locale savedLocale = LocaleUtils.setSystemLocale(res, id.mLocale); + try { + final Keyboard.Builder<Keyboard.Params> builder = + new Keyboard.Builder<Keyboard.Params>(context, new Keyboard.Params()); + if (id.isAlphabetKeyboard()) { + builder.setAutoGenerate(sKeysCache); + } + builder.load(keyboardXmlId, id); + builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); + keyboard = builder.build(); + } finally { + LocaleUtils.setSystemLocale(res, savedLocale); + } + sKeyboardCache.put(id, new SoftReference<Keyboard>(keyboard)); + + if (DEBUG_CACHE) { + Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": " + + ((ref == null) ? "LOAD" : "GCed") + " id=" + id); + } + } else if (DEBUG_CACHE) { + Log.d(TAG, "keyboard cache size=" + sKeyboardCache.size() + ": HIT id=" + id); + } + + return keyboard; + } + + // Note: The keyboard for each locale, shift state, and mode are represented as KeyboardSet + // element id that is a key in keyboard_set.xml. Also that file specifies which XML layout + // should be used for each keyboard. The KeyboardId is an internal key for Keyboard object. + private KeyboardId getKeyboardId(int keyboardSetElementId) { + final Params params = mParams; + final boolean isSymbols = (keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS + || keyboardSetElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED); + final boolean hasShortcutKey = params.mVoiceKeyEnabled + && (isSymbols != params.mVoiceKeyOnMain); + return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation, + params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey, + params.mVoiceKeyEnabled, hasShortcutKey, params.mLanguageSwitchKeyEnabled); + } + + public static class Builder { + private final Context mContext; + private final String mPackageName; + private final Resources mResources; + private final EditorInfo mEditorInfo; + + private final Params mParams = new Params(); + + public Builder(Context context, EditorInfo editorInfo) { + mContext = context; + mPackageName = context.getPackageName(); + mResources = context.getResources(); + mEditorInfo = editorInfo; + final Params params = mParams; + + params.mMode = getKeyboardMode(editorInfo); + params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO; + params.mNoSettingsKey = StringUtils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo); + } + + public Builder setScreenGeometry(int orientation, int widthPixels) { + mParams.mOrientation = orientation; + mParams.mWidth = widthPixels; + return this; + } + + // TODO: Use InputMethodSubtype object as argument. + public Builder setSubtype(Locale inputLocale, boolean asciiCapable, + boolean touchPositionCorrectionEnabled) { + final boolean deprecatedForceAscii = StringUtils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); + final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii( + mParams.mEditorInfo.imeOptions) + || deprecatedForceAscii; + mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale; + mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled; + return this; + } + + public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain, + boolean languageSwitchKeyEnabled) { + @SuppressWarnings("deprecation") + final boolean deprecatedNoMicrophone = StringUtils.inPrivateImeOptions( + null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); + final boolean noMicrophone = StringUtils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo) + || deprecatedNoMicrophone; + mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; + mParams.mVoiceKeyOnMain = voiceKeyOnMain; + mParams.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; + return this; + } + + public KeyboardSet build() { + if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED) + throw new RuntimeException("Screen geometry is not specified"); + if (mParams.mLocale == null) + throw new RuntimeException("KeyboardSet subtype is not specified"); + + final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, mParams.mLocale); + try { + parseKeyboardSet(mResources, R.xml.keyboard_set); + } catch (Exception e) { + throw new RuntimeException(e.getMessage() + " in " + + mResources.getResourceName(R.xml.keyboard_set) + + " of locale " + mParams.mLocale); + } finally { + LocaleUtils.setSystemLocale(mResources, savedLocale); + } + return new KeyboardSet(mContext, mParams); + } + + private void parseKeyboardSet(Resources res, int resId) throws XmlPullParserException, + IOException { + final XmlResourceParser parser = res.getXml(resId); + try { + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_KEYBOARD_SET.equals(tag)) { + parseKeyboardSetContent(parser); + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET); + } + } + } + } finally { + parser.close(); + } + } + + private void parseKeyboardSetContent(XmlPullParser parser) throws XmlPullParserException, + IOException { + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_ELEMENT.equals(tag)) { + parseKeyboardSetElement(parser); + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET); + } + } else if (event == XmlPullParser.END_TAG) { + final String tag = parser.getName(); + if (TAG_KEYBOARD_SET.equals(tag)) { + break; + } else { + throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEYBOARD_SET); + } + } + } + } + + private void parseKeyboardSetElement(XmlPullParser parser) throws XmlPullParserException, + IOException { + final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.KeyboardSet_Element); + try { + XmlParseUtils.checkAttributeExists(a, + R.styleable.KeyboardSet_Element_elementName, "elementName", + TAG_ELEMENT, parser); + XmlParseUtils.checkAttributeExists(a, + R.styleable.KeyboardSet_Element_elementKeyboard, "elementKeyboard", + TAG_ELEMENT, parser); + XmlParseUtils.checkEndTag(TAG_ELEMENT, parser); + + final int elementName = a.getInt( + R.styleable.KeyboardSet_Element_elementName, 0); + final int elementKeyboard = a.getResourceId( + R.styleable.KeyboardSet_Element_elementKeyboard, 0); + mParams.mKeyboardSetElementIdToXmlIdMap.put(elementName, elementKeyboard); + } finally { + a.recycle(); + } + } + + private static int getKeyboardMode(EditorInfo editorInfo) { + if (editorInfo == null) + return KeyboardId.MODE_TEXT; + + final int inputType = editorInfo.inputType; + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + + switch (inputType & InputType.TYPE_MASK_CLASS) { + case InputType.TYPE_CLASS_NUMBER: + return KeyboardId.MODE_NUMBER; + case InputType.TYPE_CLASS_DATETIME: + switch (variation) { + case InputType.TYPE_DATETIME_VARIATION_DATE: + return KeyboardId.MODE_DATE; + case InputType.TYPE_DATETIME_VARIATION_TIME: + return KeyboardId.MODE_TIME; + default: // InputType.TYPE_DATETIME_VARIATION_NORMAL + return KeyboardId.MODE_DATETIME; + } + case InputType.TYPE_CLASS_PHONE: + return KeyboardId.MODE_PHONE; + case InputType.TYPE_CLASS_TEXT: + if (InputTypeCompatUtils.isEmailVariation(variation)) { + return KeyboardId.MODE_EMAIL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { + return KeyboardId.MODE_URL; + } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { + return KeyboardId.MODE_IM; + } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { + return KeyboardId.MODE_TEXT; + } else { + return KeyboardId.MODE_TEXT; + } + default: + return KeyboardId.MODE_TEXT; + } + } + } + + // TODO: Should be removed. This is no longer required if {@link InputMethodSubtype} is + // supported. + public static String parseKeyboardLocale(Resources res, int resId) + throws XmlPullParserException, IOException { + final XmlPullParser parser = res.getXml(resId); + if (parser == null) + return ""; + int event; + while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG) { + final String tag = parser.getName(); + if (TAG_KEYBOARD_SET.equals(tag)) { + final TypedArray keyboardSetAttr = res.obtainAttributes( + Xml.asAttributeSet(parser), R.styleable.KeyboardSet); + final String locale = keyboardSetAttr.getString( + R.styleable.KeyboardSet_keyboardLocale); + keyboardSetAttr.recycle(); + return locale; + } else { + throw new XmlParseUtils.IllegalStartTag(parser, TAG_KEYBOARD_SET); + } + } + } + return ""; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index ac718fc62..42dd6206c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -18,10 +18,7 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.content.res.Resources; -import android.text.TextUtils; -import android.util.DisplayMetrics; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.InflateException; @@ -30,131 +27,66 @@ import android.view.View; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; -import com.android.inputmethod.keyboard.internal.ModifierKeyState; -import com.android.inputmethod.keyboard.internal.ShiftKeyState; +import com.android.inputmethod.keyboard.KeyboardSet.KeyboardSetException; +import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; +import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.DebugSettings; import com.android.inputmethod.latin.InputView; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.Settings; +import com.android.inputmethod.latin.SettingsValues; import com.android.inputmethod.latin.SubtypeSwitcher; import com.android.inputmethod.latin.Utils; -import java.lang.ref.SoftReference; -import java.util.HashMap; -import java.util.Locale; - -public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { +public class KeyboardSwitcher implements KeyboardState.SwitchActions { private static final String TAG = KeyboardSwitcher.class.getSimpleName(); - private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; - public static final boolean DEBUG_STATE = false; public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20110916"; - private static final int[] KEYBOARD_THEMES = { - R.style.KeyboardTheme, - R.style.KeyboardTheme_HighContrast, - R.style.KeyboardTheme_Stone, - R.style.KeyboardTheme_Stone_Bold, - R.style.KeyboardTheme_Gingerbread, - R.style.KeyboardTheme_IceCreamSandwich, + + static class KeyboardTheme { + public final String mName; + public final int mThemeId; + public final int mStyleId; + + public KeyboardTheme(String name, int themeId, int styleId) { + mName = name; + mThemeId = themeId; + mStyleId = styleId; + } + } + + private static final KeyboardTheme[] KEYBOARD_THEMES = { + new KeyboardTheme("Basic", 0, R.style.KeyboardTheme), + new KeyboardTheme("HighContrast", 1, R.style.KeyboardTheme_HighContrast), + new KeyboardTheme("Stone", 6, R.style.KeyboardTheme_Stone), + new KeyboardTheme("Stne.Bold", 7, R.style.KeyboardTheme_Stone_Bold), + new KeyboardTheme("GingerBread", 8, R.style.KeyboardTheme_Gingerbread), + new KeyboardTheme("IceCreamSandwich", 5, R.style.KeyboardTheme_IceCreamSandwich), }; private SubtypeSwitcher mSubtypeSwitcher; private SharedPreferences mPrefs; + private boolean mForceNonDistinctMultitouch; private InputView mCurrentInputView; private LatinKeyboardView mKeyboardView; private LatinIME mInputMethodService; - private String mPackageName; private Resources mResources; - // TODO: Combine these key state objects with auto mode switch state. - private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); - private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); - - private KeyboardId mMainKeyboardId; - private KeyboardId mSymbolsKeyboardId; - private KeyboardId mSymbolsShiftedKeyboardId; - - private KeyboardId mCurrentId; - private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = - new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); + private KeyboardState mState; - private KeyboardLayoutState mSavedKeyboardState = new KeyboardLayoutState(); + private KeyboardSet mKeyboardSet; /** mIsAutoCorrectionActive indicates that auto corrected word will be input instead of * what user actually typed. */ private boolean mIsAutoCorrectionActive; - // TODO: Encapsulate these state handling to separate class and combine with ShiftKeyState - // and ModifierKeyState. - private static final int SWITCH_STATE_ALPHA = 0; - private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; - private static final int SWITCH_STATE_SYMBOL = 2; - // The following states are used only on the distinct multi-touch panel devices. - private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; - private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; - private static final int SWITCH_STATE_CHORDING_ALPHA = 5; - private static final int SWITCH_STATE_CHORDING_SYMBOL = 6; - private int mSwitchState = SWITCH_STATE_ALPHA; - - private static String mLayoutSwitchBackSymbols; - - private int mThemeIndex = -1; + private KeyboardTheme mKeyboardTheme = KEYBOARD_THEMES[0]; private Context mThemeContext; private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); - private class KeyboardLayoutState { - private boolean mIsValid; - private boolean mIsAlphabetMode; - private boolean mIsShiftLocked; - private boolean mIsShifted; - - public void save() { - if (mCurrentId == null) { - return; - } - mIsAlphabetMode = isAlphabetMode(); - if (mIsAlphabetMode) { - mIsShiftLocked = isShiftLocked(); - mIsShifted = !mIsShiftLocked && isShiftedOrShiftLocked(); - } else { - mIsShiftLocked = false; - mIsShifted = mCurrentId.equals(mSymbolsShiftedKeyboardId); - } - mIsValid = true; - } - - public KeyboardId getKeyboardId() { - if (!mIsValid) return mMainKeyboardId; - - if (mIsAlphabetMode) { - return mMainKeyboardId; - } else { - return mIsShifted ? mSymbolsShiftedKeyboardId : mSymbolsKeyboardId; - } - } - - public void restore() { - if (!mIsValid) return; - mIsValid = false; - - if (mIsAlphabetMode) { - final boolean isAlphabetMode = isAlphabetMode(); - final boolean isShiftLocked = isAlphabetMode && isShiftLocked(); - final boolean isShifted = !isShiftLocked && isShiftedOrShiftLocked(); - if (mIsShiftLocked != isShiftLocked) { - toggleCapsLock(); - } else if (mIsShifted != isShifted) { - onPressShift(false); - onReleaseShift(false); - } - } - } - } - public static KeyboardSwitcher getInstance() { return sInstance; } @@ -169,52 +101,66 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private void initInternal(LatinIME ims, SharedPreferences prefs) { mInputMethodService = ims; - mPackageName = ims.getPackageName(); mResources = ims.getResources(); mPrefs = prefs; mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs)); - prefs.registerOnSharedPreferenceChangeListener(this); + mState = new KeyboardState(this); + setContextThemeWrapper(ims, getKeyboardTheme(ims, prefs)); + mForceNonDistinctMultitouch = prefs.getBoolean( + DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false); } - private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) { - final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id); - final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId); + private static KeyboardTheme getKeyboardTheme(Context context, SharedPreferences prefs) { + final String defaultIndex = context.getString(R.string.config_default_keyboard_theme_index); + final String themeIndex = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultIndex); try { - final int themeIndex = Integer.valueOf(themeId); - if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length) - return themeIndex; + final int index = Integer.valueOf(themeIndex); + if (index >= 0 && index < KEYBOARD_THEMES.length) { + return KEYBOARD_THEMES[index]; + } } catch (NumberFormatException e) { // Format error, keyboard theme is default to 0. } - Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0"); - return 0; + Log.w(TAG, "Illegal keyboard theme in preference: " + themeIndex + ", default to 0"); + return KEYBOARD_THEMES[0]; } - private void setContextThemeWrapper(Context context, int themeIndex) { - if (mThemeIndex != themeIndex) { - mThemeIndex = themeIndex; - mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]); - mKeyboardCache.clear(); + private void setContextThemeWrapper(Context context, KeyboardTheme keyboardTheme) { + if (mKeyboardTheme.mThemeId != keyboardTheme.mThemeId) { + mKeyboardTheme = keyboardTheme; + mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId); + KeyboardSet.clearKeyboardCache(); } } - public void loadKeyboard(EditorInfo editorInfo, Settings.Values settingsValues) { + public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) { + final KeyboardSet.Builder builder = new KeyboardSet.Builder(mThemeContext, editorInfo); + builder.setScreenGeometry(mThemeContext.getResources().getConfiguration().orientation, + mThemeContext.getResources().getDisplayMetrics().widthPixels); + builder.setSubtype( + mSubtypeSwitcher.getInputLocale(), + mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( + LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE), + mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( + LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); + builder.setOptions( + settingsValues.isVoiceKeyEnabled(editorInfo), + settingsValues.isVoiceKeyOnMain(), + settingsValues.isLanguageSwitchKeyEnabled(mThemeContext)); + mKeyboardSet = builder.build(); try { - mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues); - mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues); - mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues); - mLayoutSwitchBackSymbols = mResources.getString(R.string.layout_switch_back_symbols); - setKeyboard(getKeyboard(mSavedKeyboardState.getKeyboardId())); - mSavedKeyboardState.restore(); - } catch (RuntimeException e) { - Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e); - LatinImeLogger.logOnException(mMainKeyboardId.toString(), e); + mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols)); + } catch (KeyboardSetException e) { + Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); + LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause()); + return; } } public void saveKeyboardState() { - mSavedKeyboardState.save(); + if (getKeyboard() != null) { + mState.onSaveKeyboardState(); + } } public void onFinishInputView() { @@ -229,532 +175,174 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha final Keyboard oldKeyboard = mKeyboardView.getKeyboard(); mKeyboardView.setKeyboard(keyboard); mCurrentInputView.setKeyboardGeometry(keyboard.mTopPadding); - mCurrentId = keyboard.mId; - mSwitchState = getSwitchState(mCurrentId); - updateShiftLockState(keyboard); mKeyboardView.setKeyPreviewPopupEnabled( - Settings.Values.isKeyPreviewPopupEnabled(mPrefs, mResources), - Settings.Values.getKeyPreviewPopupDismissDelay(mPrefs, mResources)); - final boolean localeChanged = (oldKeyboard == null) + SettingsValues.isKeyPreviewPopupEnabled(mPrefs, mResources), + SettingsValues.getKeyPreviewPopupDismissDelay(mPrefs, mResources)); + mKeyboardView.updateAutoCorrectionState(mIsAutoCorrectionActive); + mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady()); + final boolean subtypeChanged = (oldKeyboard == null) || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); - mInputMethodService.mHandler.startDisplayLanguageOnSpacebar(localeChanged); - updateShiftState(); + final boolean needsToDisplayLanguage = mSubtypeSwitcher.needsToDisplayLanguage( + keyboard.mId.mLocale); + mKeyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, needsToDisplayLanguage); } - private int getSwitchState(KeyboardId id) { - return id.equals(mMainKeyboardId) ? SWITCH_STATE_ALPHA : SWITCH_STATE_SYMBOL_BEGIN; - } - - private void updateShiftLockState(Keyboard keyboard) { - if (mCurrentId.equals(mSymbolsShiftedKeyboardId)) { - // Symbol keyboard may have an ALT key that has a caps lock style indicator (a.k.a. - // sticky shift key). To show or dismiss the indicator, we need to call setShiftLocked() - // that takes care of the current keyboard having such ALT key or not. - keyboard.setShiftLocked(keyboard.hasShiftLockKey()); - } else if (mCurrentId.equals(mSymbolsKeyboardId)) { - // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the - // indicator, we need to call setShiftLocked(false). - keyboard.setShiftLocked(false); - } - } - - private LatinKeyboard getKeyboard(KeyboardId id) { - final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); - LatinKeyboard keyboard = (ref == null) ? null : ref.get(); - if (keyboard == null) { - final Locale savedLocale = LocaleUtils.setSystemLocale(mResources, id.mLocale); - try { - final LatinKeyboard.Builder builder = new LatinKeyboard.Builder(mThemeContext); - builder.load(id); - builder.setTouchPositionCorrectionEnabled( - mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); - keyboard = builder.build(); - } finally { - LocaleUtils.setSystemLocale(mResources, savedLocale); - } - mKeyboardCache.put(id, new SoftReference<LatinKeyboard>(keyboard)); - - if (DEBUG_CACHE) { - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": " - + ((ref == null) ? "LOAD" : "GCed") + " id=" + id - + " theme=" + Keyboard.themeName(keyboard.mThemeId)); - } - } else if (DEBUG_CACHE) { - Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT id=" + id - + " theme=" + Keyboard.themeName(keyboard.mThemeId)); - } - - keyboard.onAutoCorrectionStateChanged(mIsAutoCorrectionActive); - keyboard.setShiftLocked(false); - keyboard.setShifted(false); - // If the cached keyboard had been switched to another keyboard while the language was - // displayed on its spacebar, it might have had arbitrary text fade factor. In such case, - // we should reset the text fade factor. It is also applicable to shortcut key. - keyboard.setSpacebarTextFadeFactor(0.0f, null); - keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null); - return keyboard; - } - - private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols, - final boolean isShift, Settings.Values settingsValues) { - final int mode = Utils.getKeyboardMode(editorInfo); - final int xmlId; - switch (mode) { - case KeyboardId.MODE_PHONE: - xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone; - break; - case KeyboardId.MODE_NUMBER: - xmlId = R.xml.kbd_number; - break; - default: - if (isSymbols) { - xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols; - } else { - xmlId = R.xml.kbd_qwerty; - } - break; + public Keyboard getKeyboard() { + if (mKeyboardView != null) { + return mKeyboardView.getKeyboard(); } - - final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled(); - @SuppressWarnings("deprecation") - final boolean noMicrophone = Utils.inPrivateImeOptions( - mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo) - || Utils.inPrivateImeOptions( - null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo); - final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) - && !noMicrophone; - final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain(); - final boolean noSettingsKey = Utils.inPrivateImeOptions( - mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo); - final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey; - final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey); - final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain); - final boolean forceAscii = Utils.inPrivateImeOptions( - mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo); - final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey( - LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE); - final Locale locale = (forceAscii && !asciiCapable) - ? Locale.US : mSubtypeSwitcher.getInputLocale(); - final Configuration conf = mResources.getConfiguration(); - final DisplayMetrics dm = mResources.getDisplayMetrics(); - - return new KeyboardId( - mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation, - dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey, - voiceKeyEnabled, hasShortcutKey); - } - - public int getKeyboardMode() { - return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT; - } - - public boolean isAlphabetMode() { - return mCurrentId != null && mCurrentId.isAlphabetKeyboard(); - } - - public boolean isInputViewShown() { - return mCurrentInputView != null && mCurrentInputView.isShown(); + return null; } - public boolean isKeyboardAvailable() { - if (mKeyboardView != null) - return mKeyboardView.getKeyboard() != null; - return false; + /** + * Update keyboard shift state triggered by connected EditText status change. + */ + public void updateShiftState() { + mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); } - public LatinKeyboard getLatinKeyboard() { - if (mKeyboardView != null) { - final Keyboard keyboard = mKeyboardView.getKeyboard(); - if (keyboard instanceof LatinKeyboard) - return (LatinKeyboard)keyboard; + public void onPressKey(int code) { + if (isVibrateAndSoundFeedbackRequired()) { + mInputMethodService.hapticAndAudioFeedback(code); } - return null; + mState.onPressKey(code); } - public boolean isShiftedOrShiftLocked() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isShiftedOrShiftLocked(); - return false; + public void onReleaseKey(int code, boolean withSliding) { + mState.onReleaseKey(code, withSliding); } - public boolean isShiftLocked() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isShiftLocked(); - return false; + public void onCancelInput() { + mState.onCancelInput(isSinglePointer()); } - private boolean isShiftLockShifted() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isShiftLockShifted(); - return false; + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET)); } - public boolean isAutomaticTemporaryUpperCase() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isAutomaticTemporaryUpperCase(); - return false; + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetManualShiftedKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED)); } - public boolean isManualTemporaryUpperCase() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isManualTemporaryUpperCase(); - return false; + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetAutomaticShiftedKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED)); } - private boolean isManualTemporaryUpperCaseFromAuto() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - return latinKeyboard.isManualTemporaryUpperCaseFromAuto(); - return false; + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetShiftLockedKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED)); } - private void setManualTemporaryUpperCase(boolean shifted) { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) { - // On non-distinct multi touch panel device, we should also turn off the shift locked - // state when shift key is pressed to go to normal mode. - // On the other hand, on distinct multi touch panel device, turning off the shift locked - // state with shift key pressing is handled by onReleaseShift(). - if (!hasDistinctMultitouch() && !shifted && latinKeyboard.isShiftLocked()) { - latinKeyboard.setShiftLocked(false); - } - if (latinKeyboard.setShifted(shifted)) { - mKeyboardView.invalidateAllKeys(); - } - } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setAlphabetShiftLockShiftedKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED)); } - private void setShiftLocked(boolean shiftLocked) { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null && latinKeyboard.setShiftLocked(shiftLocked)) { - mKeyboardView.invalidateAllKeys(); - } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setSymbolsKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS)); } - /** - * Toggle keyboard shift state triggered by user touch event. - */ - public void toggleShift() { - mInputMethodService.mHandler.cancelUpdateShiftState(); - if (DEBUG_STATE) - Log.d(TAG, "toggleShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - if (isAlphabetMode()) { - setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); - } else { - toggleShiftInSymbol(); - } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void setSymbolsShiftedKeyboard() { + setKeyboard(mKeyboardSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED)); } - public void toggleCapsLock() { - mInputMethodService.mHandler.cancelUpdateShiftState(); - if (DEBUG_STATE) - Log.d(TAG, "toggleCapsLock:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - if (isAlphabetMode()) { - if (isShiftLocked()) { - // Shift key is long pressed while caps lock state, we will toggle back to normal - // state. And mark as if shift key is released. - setShiftLocked(false); - mShiftKeyState.onRelease(); - } else { - setShiftLocked(true); - } - } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void requestUpdatingShiftState() { + mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState()); } - private void setAutomaticTemporaryUpperCase() { - if (mKeyboardView == null) return; - final Keyboard keyboard = mKeyboardView.getKeyboard(); - if (keyboard == null) return; - keyboard.setAutomaticTemporaryUpperCase(); - mKeyboardView.invalidateAllKeys(); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void startDoubleTapTimer() { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.startDoubleTapTimer(); + } } - /** - * Update keyboard shift state triggered by connected EditText status change. - */ - public void updateShiftState() { - final ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "updateShiftState:" - + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + shiftKeyState - + " isAlphabetMode=" + isAlphabetMode() - + " isShiftLocked=" + isShiftLocked()); - if (isAlphabetMode()) { - if (!isShiftLocked() && !shiftKeyState.isIgnoring()) { - if (shiftKeyState.isReleasing() && mInputMethodService.getCurrentAutoCapsState()) { - // Only when shift key is releasing, automatic temporary upper case will be set. - setAutomaticTemporaryUpperCase(); - } else { - setManualTemporaryUpperCase(shiftKeyState.isMomentary()); - } - } - } else { - // In symbol keyboard mode, we should clear shift key state because only alphabet - // keyboard has shift key. - shiftKeyState.onRelease(); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void cancelDoubleTapTimer() { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.cancelDoubleTapTimer(); } } - public void changeKeyboardMode() { - if (DEBUG_STATE) - Log.d(TAG, "changeKeyboardMode:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState); - toggleKeyboardMode(); - if (isShiftLocked() && isAlphabetMode()) - setShiftLocked(true); - updateShiftState(); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public boolean isInDoubleTapTimeout() { + final LatinKeyboardView keyboardView = getKeyboardView(); + return (keyboardView != null) + ? keyboardView.getTimerProxy().isInDoubleTapTimeout() : false; } - public void onPressShift(boolean withSliding) { - if (!isKeyboardAvailable()) - return; - ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "onPressShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); - if (isAlphabetMode()) { - if (isShiftLocked()) { - // Shift key is pressed while caps lock state, we will treat this state as shifted - // caps lock state and mark as if shift key pressed while normal state. - shiftKeyState.onPress(); - setManualTemporaryUpperCase(true); - } else if (isAutomaticTemporaryUpperCase()) { - // Shift key is pressed while automatic temporary upper case, we have to move to - // manual temporary upper case. - shiftKeyState.onPress(); - setManualTemporaryUpperCase(true); - } else if (isShiftedOrShiftLocked()) { - // In manual upper case state, we just record shift key has been pressing while - // shifted state. - shiftKeyState.onPressOnShifted(); - } else { - // In base layout, chording or manual temporary upper case mode is started. - shiftKeyState.onPress(); - toggleShift(); - } - } else { - // In symbol mode, just toggle symbol and symbol more keyboard. - shiftKeyState.onPress(); - toggleShift(); - mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void startLongPressTimer(int code) { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.startLongPressTimer(code); } } - public void onReleaseShift(boolean withSliding) { - if (!isKeyboardAvailable()) - return; - ShiftKeyState shiftKeyState = mShiftKeyState; - if (DEBUG_STATE) - Log.d(TAG, "onReleaseShift:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + shiftKeyState + " sliding=" + withSliding); - if (isAlphabetMode()) { - if (shiftKeyState.isMomentary()) { - // After chording input while normal state. - toggleShift(); - } else if (isShiftLocked() && !isShiftLockShifted() && shiftKeyState.isPressing() - && !withSliding) { - // Shift has been long pressed, ignore this release. - } else if (isShiftLocked() && !shiftKeyState.isIgnoring() && !withSliding) { - // Shift has been pressed without chording while caps lock state. - toggleCapsLock(); - // To be able to turn off caps lock by "double tap" on shift key, we should ignore - // the second tap of the "double tap" from now for a while because we just have - // already turned off caps lock above. - mKeyboardView.startIgnoringDoubleTap(); - } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted() - && !withSliding) { - // Shift has been pressed without chording while shifted state. - toggleShift(); - } else if (isManualTemporaryUpperCaseFromAuto() && shiftKeyState.isPressing() - && !withSliding) { - // Shift has been pressed without chording while manual temporary upper case - // transited from automatic temporary upper case. - toggleShift(); - } - } else { - // In symbol mode, snap back to the previous keyboard mode if the user chords the shift - // key and another key, then releases the shift key. - if (mSwitchState == SWITCH_STATE_CHORDING_SYMBOL) { - toggleShift(); - } - } - shiftKeyState.onRelease(); - } - - public void onPressSymbol() { - if (DEBUG_STATE) - Log.d(TAG, "onPressSymbol:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " symbolKeyState=" + mSymbolKeyState); - changeKeyboardMode(); - mSymbolKeyState.onPress(); - mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; - } - - public void onReleaseSymbol() { - if (DEBUG_STATE) - Log.d(TAG, "onReleaseSymbol:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " symbolKeyState=" + mSymbolKeyState); - // Snap back to the previous keyboard mode if the user chords the mode change key and - // another key, then releases the mode change key. - if (mSwitchState == SWITCH_STATE_CHORDING_ALPHA) { - changeKeyboardMode(); + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void cancelLongPressTimer() { + final LatinKeyboardView keyboardView = getKeyboardView(); + if (keyboardView != null) { + final TimerProxy timer = keyboardView.getTimerProxy(); + timer.cancelLongPressTimer(); } - mSymbolKeyState.onRelease(); - } - - public void onOtherKeyPressed() { - if (DEBUG_STATE) - Log.d(TAG, "onOtherKeyPressed:" - + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() - + " shiftKeyState=" + mShiftKeyState - + " symbolKeyState=" + mSymbolKeyState); - mShiftKeyState.onOtherKeyPressed(); - mSymbolKeyState.onOtherKeyPressed(); } - public void onCancelInput() { - // Snap back to the previous keyboard mode if the user cancels sliding input. - if (getPointerCount() == 1) { - if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { - changeKeyboardMode(); - } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) { - toggleShift(); - } - } + // Implements {@link KeyboardState.SwitchActions}. + @Override + public void hapticAndAudioFeedback(int code) { + mInputMethodService.hapticAndAudioFeedback(code); } - private void toggleShiftInSymbol() { - if (isAlphabetMode()) - return; - final LatinKeyboard keyboard; - if (mCurrentId.equals(mSymbolsKeyboardId) - || !mCurrentId.equals(mSymbolsShiftedKeyboardId)) { - keyboard = getKeyboard(mSymbolsShiftedKeyboardId); - } else { - keyboard = getKeyboard(mSymbolsKeyboardId); - } - setKeyboard(keyboard); + public void onLongPressTimeout(int code) { + mState.onLongPressTimeout(code); } public boolean isInMomentarySwitchState() { - return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL - || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; + return mState.isInMomentarySwitchState(); } - public boolean isVibrateAndSoundFeedbackRequired() { + private boolean isVibrateAndSoundFeedbackRequired() { return mKeyboardView != null && !mKeyboardView.isInSlidingKeyInput(); } - private int getPointerCount() { - return mKeyboardView == null ? 0 : mKeyboardView.getPointerCount(); - } - - private void toggleKeyboardMode() { - if (mCurrentId.equals(mMainKeyboardId)) { - setKeyboard(getKeyboard(mSymbolsKeyboardId)); - } else { - setKeyboard(getKeyboard(mMainKeyboardId)); - } + private boolean isSinglePointer() { + return mKeyboardView != null && mKeyboardView.getPointerCount() == 1; } public boolean hasDistinctMultitouch() { return mKeyboardView != null && mKeyboardView.hasDistinctMultitouch(); } - private static boolean isSpaceCharacter(int c) { - return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; - } - - private static boolean isLayoutSwitchBackCharacter(int c) { - if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false; - if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true; - return false; - } - /** - * Updates state machine to figure out when to automatically snap back to the previous mode. + * Updates state machine to figure out when to automatically switch back to the previous mode. */ - public void onKey(int code) { - if (DEBUG_STATE) - Log.d(TAG, "onKey: code=" + code + " switchState=" + mSwitchState - + " pointers=" + getPointerCount()); - switch (mSwitchState) { - case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: - // Only distinct multi touch devices can be in this state. - // On non-distinct multi touch devices, mode change key is handled by - // {@link LatinIME#onCodeInput}, not by {@link LatinIME#onPress} and - // {@link LatinIME#onRelease}. So, on such devices, {@link #mSwitchState} starts - // from {@link #SWITCH_STATE_SYMBOL_BEGIN}, or {@link #SWITCH_STATE_ALPHA}, not from - // {@link #SWITCH_STATE_MOMENTARY}. - if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - // Detected only the mode change key has been pressed, and then released. - if (mCurrentId.equals(mMainKeyboardId)) { - mSwitchState = SWITCH_STATE_ALPHA; - } else { - mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; - } - } else if (getPointerCount() == 1) { - // Snap back to the previous keyboard mode if the user pressed the mode change key - // and slid to other key, then released the finger. - // If the user cancels the sliding input, snapping back to the previous keyboard - // mode is handled by {@link #onCancelInput}. - changeKeyboardMode(); - } else { - // Chording input is being started. The keyboard mode will be snapped back to the - // previous mode in {@link onReleaseSymbol} when the mode change key is released. - mSwitchState = SWITCH_STATE_CHORDING_ALPHA; - } - break; - case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: - if (code == Keyboard.CODE_SHIFT) { - // Detected only the shift key has been pressed on symbol layout, and then released. - mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; - } else if (getPointerCount() == 1) { - // Snap back to the previous keyboard mode if the user pressed the shift key on - // symbol mode and slid to other key, then released the finger. - toggleShift(); - mSwitchState = SWITCH_STATE_SYMBOL; - } else { - // Chording input is being started. The keyboard mode will be snapped back to the - // previous mode in {@link onReleaseShift} when the shift key is released. - mSwitchState = SWITCH_STATE_CHORDING_SYMBOL; - } - break; - case SWITCH_STATE_SYMBOL_BEGIN: - if (!isSpaceCharacter(code) && code >= 0) { - mSwitchState = SWITCH_STATE_SYMBOL; - } - // Snap back to alpha keyboard mode immediately if user types a quote character. - if (isLayoutSwitchBackCharacter(code)) { - changeKeyboardMode(); - } - break; - case SWITCH_STATE_SYMBOL: - case SWITCH_STATE_CHORDING_SYMBOL: - // Snap back to alpha keyboard mode if user types one or more non-space/enter - // characters followed by a space/enter or a quote character. - if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) { - changeKeyboardMode(); - } - break; - } + public void onCodeInput(int code) { + mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState()); } public LatinKeyboardView getKeyboardView() { @@ -762,94 +350,52 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public View onCreateInputView() { - return createInputView(mThemeIndex, true); - } - - private View createInputView(final int newThemeIndex, final boolean forceRecreate) { - if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate) - return mCurrentInputView; - if (mKeyboardView != null) { mKeyboardView.closing(); } - final int oldThemeIndex = mThemeIndex; Utils.GCUtils.getInstance().reset(); boolean tryGC = true; for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { try { - setContextThemeWrapper(mInputMethodService, newThemeIndex); + setContextThemeWrapper(mInputMethodService, mKeyboardTheme); mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate( R.layout.input_view, null); tryGC = false; } catch (OutOfMemoryError e) { Log.w(TAG, "load keyboard failed: " + e); - tryGC = Utils.GCUtils.getInstance().tryGCOrWait( - oldThemeIndex + "," + newThemeIndex, e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e); } catch (InflateException e) { Log.w(TAG, "load keyboard failed: " + e); - tryGC = Utils.GCUtils.getInstance().tryGCOrWait( - oldThemeIndex + "," + newThemeIndex, e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mKeyboardTheme.mName, e); } } mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); mKeyboardView.setKeyboardActionListener(mInputMethodService); + if (mForceNonDistinctMultitouch) { + mKeyboardView.setDistinctMultitouch(false); + } // This always needs to be set since the accessibility state can // potentially change without the input view being re-created. - AccessibleKeyboardViewProxy.setView(mKeyboardView); + AccessibleKeyboardViewProxy.getInstance().setView(mKeyboardView); return mCurrentInputView; } - private void postSetInputView(final View newInputView) { - mInputMethodService.mHandler.post(new Runnable() { - @Override - public void run() { - if (newInputView != null) { - mInputMethodService.setInputView(newInputView); - } - mInputMethodService.updateInputViewShown(); - } - }); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (PREF_KEYBOARD_LAYOUT.equals(key)) { - final int themeIndex = getKeyboardThemeIndex(mInputMethodService, sharedPreferences); - postSetInputView(createInputView(themeIndex, false)); - } else if (Settings.PREF_SHOW_SETTINGS_KEY.equals(key)) { - postSetInputView(createInputView(mThemeIndex, true)); + public void onNetworkStateChanged() { + if (mKeyboardView != null) { + mKeyboardView.updateShortcutKey(SubtypeSwitcher.getInstance().isShortcutImeReady()); } } public void onAutoCorrectionStateChanged(boolean isAutoCorrection) { if (mIsAutoCorrectionActive != isAutoCorrection) { mIsAutoCorrectionActive = isAutoCorrection; - final LatinKeyboard keyboard = getLatinKeyboard(); - if (keyboard != null && keyboard.needsAutoCorrectionSpacebarLed()) { - final Key invalidatedKey = keyboard.onAutoCorrectionStateChanged(isAutoCorrection); - final LatinKeyboardView keyboardView = getKeyboardView(); - if (keyboardView != null) - keyboardView.invalidateKey(invalidatedKey); + if (mKeyboardView != null) { + mKeyboardView.updateAutoCorrectionState(isAutoCorrection); } } } - - private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) { - if (noSettingsKey) { - // Never shows the Settings key - return KeyboardId.F2KEY_MODE_SHORTCUT_IME; - } - - if (settingsKeyEnabled) { - return KeyboardId.F2KEY_MODE_SETTINGS; - } else { - // It should be alright to fall back to the Settings key on 7-inch layouts - // even when the Settings key is not explicitly enabled. - return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS; - } - } } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 04e672590..847174c0a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -17,7 +17,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -42,24 +41,26 @@ import com.android.inputmethod.compat.FrameLayoutCompatUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; +import com.android.inputmethod.latin.StringUtils; import java.util.HashMap; +import java.util.HashSet; /** * A view that renders a virtual {@link Keyboard}. * - * @attr ref R.styleable#KeyboardView_backgroundDimAmount + * @attr ref R.styleable#KeyboardView_backgroundDimAlpha * @attr ref R.styleable#KeyboardView_keyBackground * @attr ref R.styleable#KeyboardView_keyLetterRatio * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio * @attr ref R.styleable#KeyboardView_keyLabelRatio * @attr ref R.styleable#KeyboardView_keyHintLetterRatio - * @attr ref R.styleable#KeyboardView_keyUppercaseLetterRatio + * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintRatio * @attr ref R.styleable#KeyboardView_keyHintLabelRatio * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding * @attr ref R.styleable#KeyboardView_keyHintLetterPadding * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding - * @attr ref R.styleable#KeyboardView_keyUppercaseLetterPadding + * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintPadding * @attr ref R.styleable#KeyboardView_keyTextStyle * @attr ref R.styleable#KeyboardView_keyPreviewLayout * @attr ref R.styleable#KeyboardView_keyPreviewTextRatio @@ -69,8 +70,8 @@ import java.util.HashMap; * @attr ref R.styleable#KeyboardView_keyTextColorDisabled * @attr ref R.styleable#KeyboardView_keyHintLetterColor * @attr ref R.styleable#KeyboardView_keyHintLabelColor - * @attr ref R.styleable#KeyboardView_keyUppercaseLetterInactivatedColor - * @attr ref R.styleable#KeyboardView_keyUppercaseLetterActivatedColor + * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintInactivatedColor + * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintActivatedColor * @attr ref R.styleable#KeyboardView_shadowColor * @attr ref R.styleable#KeyboardView_shadowRadius */ @@ -81,7 +82,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // XML attributes protected final float mVerticalCorrection; protected final int mMoreKeysLayout; - private final float mBackgroundDimAmount; + private final int mBackgroundDimAlpha; // HORIZONTAL ELLIPSIS "...", character for popup hint. private static final String POPUP_HINT_CHAR = "\u2026"; @@ -94,6 +95,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // The maximum key label width in the proportion to the key width. private static final float MAX_LABEL_RATIO = 0.90f; + private final static int ALPHA_OPAQUE = 255; + // Main keyboard private Keyboard mKeyboard; private final KeyDrawParams mKeyDrawParams; @@ -102,7 +105,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final int mKeyPreviewLayoutId; protected final KeyPreviewDrawParams mKeyPreviewDrawParams; private boolean mShowKeyPreviewPopup = true; - private final int mDelayBeforePreview; private int mDelayAfterPreview; private ViewGroup mPreviewPlacer; @@ -111,12 +113,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private boolean mNeedsToDimBackground; /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/ private boolean mBufferNeedsUpdate; - /** The dirty region in the keyboard bitmap */ - private final Rect mDirtyRect = new Rect(); - /** The key to invalidate. */ - private Key mInvalidatedKey; - /** The dirty region for single key drawing */ - private final Rect mInvalidatedKeyRect = new Rect(); + /** True if all keys should be drawn */ + private boolean mInvalidateAllKeys; + /** The keys that should be drawn */ + private final HashSet<Key> mInvalidatedKeys = new HashSet<Key>(); + /** The region of invalidated keys */ + private final Rect mInvalidatedKeysRect = new Rect(); /** The keyboard bitmap buffer for faster updates */ private Bitmap mBuffer; /** The canvas for the above mutable keyboard bitmap */ @@ -134,8 +136,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final DrawingHandler mDrawingHandler = new DrawingHandler(this); public static class DrawingHandler extends StaticInnerHandlerWrapper<KeyboardView> { - private static final int MSG_SHOW_KEY_PREVIEW = 1; - private static final int MSG_DISMISS_KEY_PREVIEW = 2; + private static final int MSG_DISMISS_KEY_PREVIEW = 1; public DrawingHandler(KeyboardView outerInstance) { super(outerInstance); @@ -147,36 +148,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (keyboardView == null) return; final PointerTracker tracker = (PointerTracker) msg.obj; switch (msg.what) { - case MSG_SHOW_KEY_PREVIEW: - keyboardView.showKey(msg.arg1, tracker); - break; case MSG_DISMISS_KEY_PREVIEW: tracker.getKeyPreviewText().setVisibility(View.INVISIBLE); break; } } - public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) { - removeMessages(MSG_SHOW_KEY_PREVIEW); - final KeyboardView keyboardView = getOuterInstance(); - if (keyboardView == null) return; - if (tracker.getKeyPreviewText().getVisibility() == VISIBLE || delay == 0) { - // Show right away, if it's already visible and finger is moving around - keyboardView.showKey(keyIndex, tracker); - } else { - sendMessageDelayed( - obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay); - } - } - - public void cancelShowKeyPreview(PointerTracker tracker) { - removeMessages(MSG_SHOW_KEY_PREVIEW, tracker); - } - - public void cancelAllShowKeyPreviews() { - removeMessages(MSG_SHOW_KEY_PREVIEW); - } - public void dismissKeyPreview(long delay, PointerTracker tracker) { sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); } @@ -190,12 +167,11 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } public void cancelAllMessages() { - cancelAllShowKeyPreviews(); cancelAllDismissKeyPreviews(); } } - private static class KeyDrawParams { + /* package */ static class KeyDrawParams { // XML attributes public final int mKeyTextColor; public final int mKeyTextInactivatedColor; @@ -203,20 +179,20 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public final float mKeyLabelHorizontalPadding; public final float mKeyHintLetterPadding; public final float mKeyPopupHintLetterPadding; - public final float mKeyUppercaseLetterPadding; + public final float mKeyShiftedLetterHintPadding; public final int mShadowColor; public final float mShadowRadius; public final Drawable mKeyBackground; public final int mKeyHintLetterColor; public final int mKeyHintLabelColor; - public final int mKeyUppercaseLetterInactivatedColor; - public final int mKeyUppercaseLetterActivatedColor; + public final int mKeyShiftedLetterHintInactivatedColor; + public final int mKeyShiftedLetterHintActivatedColor; - private final float mKeyLetterRatio; + /* package */ final float mKeyLetterRatio; private final float mKeyLargeLetterRatio; private final float mKeyLabelRatio; private final float mKeyHintLetterRatio; - private final float mKeyUppercaseLetterRatio; + private final float mKeyShiftedLetterHintRatio; private final float mKeyHintLabelRatio; private static final float UNDEFINED_RATIO = -1.0f; @@ -225,8 +201,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public int mKeyLargeLetterSize; public int mKeyLabelSize; public int mKeyHintLetterSize; - public int mKeyUppercaseLetterSize; + public int mKeyShiftedLetterHintSize; public int mKeyHintLabelSize; + public int mAnimAlpha; public KeyDrawParams(TypedArray a) { mKeyBackground = a.getDrawable(R.styleable.KeyboardView_keyBackground); @@ -244,8 +221,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } mKeyLargeLetterRatio = getRatio(a, R.styleable.KeyboardView_keyLargeLetterRatio); mKeyHintLetterRatio = getRatio(a, R.styleable.KeyboardView_keyHintLetterRatio); - mKeyUppercaseLetterRatio = getRatio(a, - R.styleable.KeyboardView_keyUppercaseLetterRatio); + mKeyShiftedLetterHintRatio = getRatio(a, + R.styleable.KeyboardView_keyShiftedLetterHintRatio); mKeyHintLabelRatio = getRatio(a, R.styleable.KeyboardView_keyHintLabelRatio); mKeyLabelHorizontalPadding = a.getDimension( R.styleable.KeyboardView_keyLabelHorizontalPadding, 0); @@ -253,17 +230,17 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { R.styleable.KeyboardView_keyHintLetterPadding, 0); mKeyPopupHintLetterPadding = a.getDimension( R.styleable.KeyboardView_keyPopupHintLetterPadding, 0); - mKeyUppercaseLetterPadding = a.getDimension( - R.styleable.KeyboardView_keyUppercaseLetterPadding, 0); + mKeyShiftedLetterHintPadding = a.getDimension( + R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0); mKeyTextColor = a.getColor(R.styleable.KeyboardView_keyTextColor, 0xFF000000); mKeyTextInactivatedColor = a.getColor( R.styleable.KeyboardView_keyTextInactivatedColor, 0xFF000000); mKeyHintLetterColor = a.getColor(R.styleable.KeyboardView_keyHintLetterColor, 0); mKeyHintLabelColor = a.getColor(R.styleable.KeyboardView_keyHintLabelColor, 0); - mKeyUppercaseLetterInactivatedColor = a.getColor( - R.styleable.KeyboardView_keyUppercaseLetterInactivatedColor, 0); - mKeyUppercaseLetterActivatedColor = a.getColor( - R.styleable.KeyboardView_keyUppercaseLetterActivatedColor, 0); + mKeyShiftedLetterHintInactivatedColor = a.getColor( + R.styleable.KeyboardView_keyShiftedLetterHintInactivatedColor, 0); + mKeyShiftedLetterHintActivatedColor = a.getColor( + R.styleable.KeyboardView_keyShiftedLetterHintActivatedColor, 0); mKeyTextStyle = Typeface.defaultFromStyle( a.getInt(R.styleable.KeyboardView_keyTextStyle, Typeface.NORMAL)); mShadowColor = a.getColor(R.styleable.KeyboardView_shadowColor, 0); @@ -279,12 +256,18 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mKeyLabelSize = (int)(keyHeight * mKeyLabelRatio); mKeyLargeLetterSize = (int)(keyHeight * mKeyLargeLetterRatio); mKeyHintLetterSize = (int)(keyHeight * mKeyHintLetterRatio); - mKeyUppercaseLetterSize = (int)(keyHeight * mKeyUppercaseLetterRatio); + mKeyShiftedLetterHintSize = (int)(keyHeight * mKeyShiftedLetterHintRatio); mKeyHintLabelSize = (int)(keyHeight * mKeyHintLabelRatio); } + + public void brendAlpha(Paint paint) { + final int color = paint.getColor(); + paint.setARGB((paint.getAlpha() * mAnimAlpha) / ALPHA_OPAQUE, + Color.red(color), Color.green(color), Color.blue(color)); + } } - protected static class KeyPreviewDrawParams { + /* package */ static class KeyPreviewDrawParams { // XML attributes. public final Drawable mPreviewBackground; public final Drawable mPreviewLeftBackground; @@ -295,6 +278,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public final int mPreviewOffset; public final int mPreviewHeight; public final Typeface mKeyTextStyle; + public final int mLingerTimeout; private final float mPreviewTextRatio; private final float mKeyLetterRatio; @@ -324,6 +308,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { R.styleable.KeyboardView_keyPreviewHeight, 80); mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio); mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0); + mLingerTimeout = a.getInt(R.styleable.KeyboardView_keyPreviewLingerTimeout, 0); mKeyLetterRatio = keyDrawParams.mKeyLetterRatio; mKeyTextStyle = keyDrawParams.mKeyTextStyle; @@ -360,21 +345,17 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mVerticalCorrection = a.getDimensionPixelOffset( R.styleable.KeyboardView_verticalCorrection, 0); mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0); - mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f); + mBackgroundDimAlpha = a.getInt(R.styleable.KeyboardView_backgroundDimAlpha, 0); a.recycle(); - final Resources res = getResources(); - - mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview); - mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview); + mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout; mPaint.setAntiAlias(true); mPaint.setTextAlign(Align.CENTER); - mPaint.setAlpha(255); } // Read fraction value in TypedArray as float. - private static float getRatio(TypedArray a, int index) { + /* package */ static float getRatio(TypedArray a, int index) { return a.getFraction(index, 1000, 1000, 1) / 1000.0f; } @@ -386,16 +367,14 @@ 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 dismissing preview - mDrawingHandler.cancelAllShowKeyPreviews(); + // Remove any pending messages. + mDrawingHandler.cancelAllMessages(); if (mKeyboard != null) { PointerTracker.dismissAllKeyPreviews(); } mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(keyboard); requestLayout(); - mDirtyRect.set(0, 0, getWidth(), getHeight()); - mBufferNeedsUpdate = true; invalidateAllKeys(); final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mKeyDrawParams.updateKeyHeight(keyHeight); @@ -462,49 +441,50 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (mBuffer != null) mBuffer.recycle(); mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - mDirtyRect.union(0, 0, width, height); + mInvalidateAllKeys = true; if (mCanvas != null) { mCanvas.setBitmap(mBuffer); } else { mCanvas = new Canvas(mBuffer); } } - final Canvas canvas = mCanvas; - canvas.clipRect(mDirtyRect, Op.REPLACE); - canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); if (mKeyboard == null) return; - final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase(); + final Canvas canvas = mCanvas; + final Paint paint = mPaint; final KeyDrawParams params = mKeyDrawParams; - if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) { - // Draw a single key. - final int keyDrawX = mInvalidatedKey.mX + mInvalidatedKey.mVisualInsetsLeft - + getPaddingLeft(); - final int keyDrawY = mInvalidatedKey.mY + getPaddingTop(); - canvas.translate(keyDrawX, keyDrawY); - onBufferDrawKey(mInvalidatedKey, mKeyboard, canvas, mPaint, params, - isManualTemporaryUpperCase); - canvas.translate(-keyDrawX, -keyDrawY); - } else { + + if (mInvalidateAllKeys || mInvalidatedKeys.isEmpty()) { + mInvalidatedKeysRect.set(0, 0, getWidth(), getHeight()); + canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE); + canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); // Draw all keys. for (final Key key : mKeyboard.mKeys) { - final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft(); - final int keyDrawY = key.mY + getPaddingTop(); - canvas.translate(keyDrawX, keyDrawY); - onBufferDrawKey(key, mKeyboard, canvas, mPaint, params, isManualTemporaryUpperCase); - canvas.translate(-keyDrawX, -keyDrawY); + onDrawKey(key, canvas, paint, params); + } + } else { + // Draw invalidated keys. + for (final Key key : mInvalidatedKeys) { + final int x = key.mX + getPaddingLeft(); + final int y = key.mY + getPaddingTop(); + mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight); + canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE); + canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); + onDrawKey(key, canvas, paint, params); } } // Overlay a dark rectangle to dim the entire keyboard if (mNeedsToDimBackground) { - mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); - canvas.drawRect(0, 0, width, height, mPaint); + paint.setColor(Color.BLACK); + paint.setAlpha(mBackgroundDimAlpha); + canvas.drawRect(0, 0, width, height, paint); } - mInvalidatedKey = null; - mDirtyRect.setEmpty(); + mInvalidatedKeys.clear(); + mInvalidatedKeysRect.setEmpty(); + mInvalidateAllKeys = false; } public void dimEntireKeyboard(boolean dimmed) { @@ -515,47 +495,61 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } } - private static void onBufferDrawKey(final Key key, final Keyboard keyboard, final Canvas canvas, - Paint paint, KeyDrawParams params, boolean isManualTemporaryUpperCase) { - final boolean debugShowAlign = LatinImeLogger.sVISUALDEBUG; - // Draw key background. + private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { + final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft(); + final int keyDrawY = key.mY + getPaddingTop(); + canvas.translate(keyDrawX, keyDrawY); + + params.mAnimAlpha = ALPHA_OPAQUE; if (!key.isSpacer()) { - final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight - + params.mPadding.left + params.mPadding.right; - final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom; - final int bgX = -params.mPadding.left; - final int bgY = -params.mPadding.top; - final int[] drawableState = key.getCurrentDrawableState(); - final Drawable background = params.mKeyBackground; - background.setState(drawableState); - final Rect bounds = background.getBounds(); - if (bgWidth != bounds.right || bgHeight != bounds.bottom) { - background.setBounds(0, 0, bgWidth, bgHeight); - } - canvas.translate(bgX, bgY); - background.draw(canvas); - if (debugShowAlign) { - drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint()); - } - canvas.translate(-bgX, -bgY); + onDrawKeyBackground(key, canvas, params); } + onDrawKeyTopVisuals(key, canvas, paint, params); - // Draw key top visuals. + canvas.translate(-keyDrawX, -keyDrawY); + } + + // Draw key background. + protected void onDrawKeyBackground(Key key, Canvas canvas, KeyDrawParams params) { + final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight + + params.mPadding.left + params.mPadding.right; + final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom; + final int bgX = -params.mPadding.left; + final int bgY = -params.mPadding.top; + final int[] drawableState = key.getCurrentDrawableState(); + final Drawable background = params.mKeyBackground; + background.setState(drawableState); + final Rect bounds = background.getBounds(); + if (bgWidth != bounds.right || bgHeight != bounds.bottom) { + background.setBounds(0, 0, bgWidth, bgHeight); + } + canvas.translate(bgX, bgY); + background.draw(canvas); + if (LatinImeLogger.sVISUALDEBUG) { + drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint()); + } + canvas.translate(-bgX, -bgY); + } + + // Draw key top visuals. + protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; final int keyHeight = key.mHeight; final float centerX = keyWidth * 0.5f; final float centerY = keyHeight * 0.5f; - if (debugShowAlign) { + if (LatinImeLogger.sVISUALDEBUG) { drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint()); } // Draw key label. - final Drawable icon = key.getIcon(); + final Drawable icon = key.getIcon(mKeyboard.mIconsSet); + if (icon != null) { + icon.setAlpha(params.mAnimAlpha); + } float positionX = centerX; if (key.mLabel != null) { - // Switch the character to uppercase if shift is pressed - final CharSequence label = keyboard.adjustLabelCase(key.mLabel); + final String label = key.mLabel; // 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, @@ -598,11 +592,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint))); } - if (key.hasUppercaseLetter() && isManualTemporaryUpperCase) { - paint.setColor(params.mKeyTextInactivatedColor); - } else { - paint.setColor(params.mKeyTextColor); - } + paint.setColor(key.isShiftedLetterActivated() + ? params.mKeyTextInactivatedColor : params.mKeyTextColor); if (key.isEnabled()) { // Set a drop shadow for the text paint.setShadowLayer(params.mShadowRadius, 0, 0, params.mShadowColor); @@ -610,6 +601,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // Make label invisible paint.setColor(Color.TRANSPARENT); } + params.brendAlpha(paint); canvas.drawText(label, 0, label.length(), positionX, baseline, paint); // Turn off drop shadow and reset x-scale. paint.setShadowLayer(0, 0, 0, 0); @@ -628,7 +620,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } } - if (debugShowAlign) { + if (LatinImeLogger.sVISUALDEBUG) { final Paint line = new Paint(); drawHorizontalLine(canvas, baseline, keyWidth, 0xc0008000, line); drawVerticalLine(canvas, positionX, keyHeight, 0xc0800080, line); @@ -637,23 +629,24 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // Draw hint label. if (key.mHintLabel != null) { - final CharSequence hint = key.mHintLabel; + final String hint = key.mHintLabel; final int hintColor; final int hintSize; if (key.hasHintLabel()) { hintColor = params.mKeyHintLabelColor; hintSize = params.mKeyHintLabelSize; paint.setTypeface(Typeface.DEFAULT); - } else if (key.hasUppercaseLetter()) { - hintColor = isManualTemporaryUpperCase - ? params.mKeyUppercaseLetterActivatedColor - : params.mKeyUppercaseLetterInactivatedColor; - hintSize = params.mKeyUppercaseLetterSize; + } else if (key.hasShiftedLetterHint()) { + hintColor = key.isShiftedLetterActivated() + ? params.mKeyShiftedLetterHintActivatedColor + : params.mKeyShiftedLetterHintInactivatedColor; + hintSize = params.mKeyShiftedLetterHintSize; } else { // key.hasHintLetter() hintColor = params.mKeyHintLetterColor; hintSize = params.mKeyHintLetterSize; } paint.setColor(hintColor); + params.brendAlpha(paint); paint.setTextSize(hintSize); final float hintX, hintY; if (key.hasHintLabel()) { @@ -663,9 +656,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2; hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2; paint.setTextAlign(Align.LEFT); - } else if (key.hasUppercaseLetter()) { + } else if (key.hasShiftedLetterHint()) { // The hint label is placed at top-right corner of the key. Used mainly on tablet. - hintX = keyWidth - params.mKeyUppercaseLetterPadding + hintX = keyWidth - params.mKeyShiftedLetterHintPadding - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; hintY = -paint.ascent(); paint.setTextAlign(Align.CENTER); @@ -678,7 +671,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } canvas.drawText(hint, 0, hint.length(), hintX, hintY, paint); - if (debugShowAlign) { + if (LatinImeLogger.sVISUALDEBUG) { final Paint line = new Paint(); drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line); drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line); @@ -703,33 +696,38 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight); - if (debugShowAlign) { + if (LatinImeLogger.sVISUALDEBUG) { final Paint line = new Paint(); drawVerticalLine(canvas, alignX, keyHeight, 0xc0800080, line); drawRectangle(canvas, iconX, iconY, iconWidth, iconHeight, 0x80c00000, line); } } - // Draw popup hint "..." at the bottom right corner of the key. - if ((key.hasPopupHint() && key.mMoreKeys != null && key.mMoreKeys.length > 0) - || key.needsSpecialPopupHint()) { - paint.setTextSize(params.mKeyHintLetterSize); - paint.setColor(params.mKeyHintLabelColor); - paint.setTextAlign(Align.CENTER); - final float hintX = keyWidth - params.mKeyHintLetterPadding - - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; - final float hintY = keyHeight - params.mKeyPopupHintLetterPadding; - canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint); - - if (debugShowAlign) { - final Paint line = new Paint(); - drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line); - drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line); - } + if (key.hasPopupHint() && key.mMoreKeys != null && key.mMoreKeys.length > 0) { + drawKeyPopupHint(key, canvas, paint, params); } } - private static final Rect sTextBounds = new Rect(); + // Draw popup hint "..." at the bottom right corner of the key. + protected void drawKeyPopupHint(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { + final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; + final int keyHeight = key.mHeight; + + paint.setTextSize(params.mKeyHintLetterSize); + paint.setColor(params.mKeyHintLabelColor); + params.brendAlpha(paint); + paint.setTextAlign(Align.CENTER); + final float hintX = keyWidth - params.mKeyHintLetterPadding + - getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2; + final float hintY = keyHeight - params.mKeyPopupHintLetterPadding; + canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint); + + if (LatinImeLogger.sVISUALDEBUG) { + final Paint line = new Paint(); + drawHorizontalLine(canvas, (int)hintY, keyWidth, 0xc0808000, line); + drawVerticalLine(canvas, (int)hintX, keyHeight, 0xc0808000, line); + } + } private static int getCharGeometryCacheKey(char reference, Paint paint) { final int labelSize = (int)paint.getTextSize(); @@ -746,42 +744,45 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } } - private static float getCharHeight(char[] character, Paint paint) { + // Working variable for the following methods. + private final Rect mTextBounds = new Rect(); + + private float getCharHeight(char[] character, Paint paint) { final Integer key = getCharGeometryCacheKey(character[0], paint); final Float cachedValue = sTextHeightCache.get(key); if (cachedValue != null) return cachedValue; - paint.getTextBounds(character, 0, 1, sTextBounds); - final float height = sTextBounds.height(); + paint.getTextBounds(character, 0, 1, mTextBounds); + final float height = mTextBounds.height(); sTextHeightCache.put(key, height); return height; } - private static float getCharWidth(char[] character, Paint paint) { + private float getCharWidth(char[] character, Paint paint) { final Integer key = getCharGeometryCacheKey(character[0], paint); final Float cachedValue = sTextWidthCache.get(key); if (cachedValue != null) return cachedValue; - paint.getTextBounds(character, 0, 1, sTextBounds); - final float width = sTextBounds.width(); + paint.getTextBounds(character, 0, 1, mTextBounds); + final float width = mTextBounds.width(); sTextWidthCache.put(key, width); return width; } - private static float getLabelWidth(CharSequence label, Paint paint) { - paint.getTextBounds(label.toString(), 0, label.length(), sTextBounds); - return sTextBounds.width(); + protected float getLabelWidth(CharSequence label, Paint paint) { + paint.getTextBounds(label.toString(), 0, label.length(), mTextBounds); + return mTextBounds.width(); } - public float getDefaultLabelWidth(CharSequence label, Paint paint) { + public float getDefaultLabelWidth(String label, Paint paint) { paint.setTextSize(mKeyDrawParams.mKeyLabelSize); paint.setTypeface(mKeyDrawParams.mKeyTextStyle); return getLabelWidth(label, paint); } - private static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width, + protected static void drawIcon(Canvas canvas, Drawable icon, int x, int y, int width, int height) { canvas.translate(x, y); icon.setBounds(0, 0, width, height); @@ -830,20 +831,14 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } @Override - public void showKeyPreview(int keyIndex, PointerTracker tracker) { + public void showKeyPreview(PointerTracker tracker) { if (mShowKeyPreviewPopup) { - mDrawingHandler.showKeyPreview(mDelayBeforePreview, keyIndex, tracker); + showKey(tracker); } } @Override - public void cancelShowKeyPreview(PointerTracker tracker) { - mDrawingHandler.cancelShowKeyPreview(tracker); - } - - @Override public void dismissKeyPreview(PointerTracker tracker) { - mDrawingHandler.cancelShowKeyPreview(tracker); mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker); } @@ -858,7 +853,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { keyPreview, FrameLayoutCompatUtils.newLayoutParam(mPreviewPlacer, 0, 0)); } - private void showKey(final int keyIndex, PointerTracker tracker) { + private void showKey(PointerTracker tracker) { final TextView previewText = tracker.getKeyPreviewText(); // If the key preview has no parent view yet, add it to the ViewGroup which can place // key preview absolutely in SoftInputWindow. @@ -867,8 +862,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } mDrawingHandler.cancelDismissKeyPreview(tracker); - final Key key = tracker.getKey(keyIndex); - // If keyIndex is invalid or IME is already closed, we must not show key preview. + final Key key = tracker.getKey(); + // If key is invalid or IME is already closed, we must not show key preview. // Trying to show key preview while root window is closed causes // WindowManager.BadTokenException. if (key == null) @@ -877,22 +872,21 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { final KeyPreviewDrawParams params = mKeyPreviewDrawParams; final int keyDrawX = key.mX + key.mVisualInsetsLeft; final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; - // What we show as preview should match what we show on key top in onBufferDraw(). + // What we show as preview should match what we show on a key top in onBufferDraw(). if (key.mLabel != null) { // TODO Should take care of temporaryShiftLabel here. previewText.setCompoundDrawables(null, null, null, null); - if (key.mLabel.length() > 1) { + if (StringUtils.codePointCount(key.mLabel) > 1) { previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mKeyLetterSize); previewText.setTypeface(Typeface.DEFAULT_BOLD); } else { previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mPreviewTextSize); previewText.setTypeface(params.mKeyTextStyle); } - previewText.setText(mKeyboard.adjustLabelCase(key.mLabel)); + previewText.setText(key.mLabel); } else { - final Drawable previewIcon = key.getPreviewIcon(); previewText.setCompoundDrawables(null, null, null, - previewIcon != null ? previewIcon : key.getIcon()); + key.getPreviewIcon(mKeyboard.mIconsSet)); previewText.setText(null); } previewText.setBackgroundDrawable(params.mPreviewBackground); @@ -906,12 +900,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + params.mCoordinates[0]; final int previewY = key.mY - previewHeight + params.mCoordinates[1] + params.mPreviewOffset; - if (previewX < 0 && params.mPreviewLeftBackground != null) { - previewText.setBackgroundDrawable(params.mPreviewLeftBackground); + if (previewX < 0) { previewX = 0; - } else if (previewX + previewWidth > getWidth() && params.mPreviewRightBackground != null) { - previewText.setBackgroundDrawable(params.mPreviewRightBackground); + if (params.mPreviewLeftBackground != null) { + previewText.setBackgroundDrawable(params.mPreviewLeftBackground); + } + } else if (previewX > getWidth() - previewWidth) { previewX = getWidth() - previewWidth; + if (params.mPreviewRightBackground != null) { + previewText.setBackgroundDrawable(params.mPreviewRightBackground); + } } // Set the preview background state @@ -930,7 +928,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { * @see #invalidateKey(Key) */ public void invalidateAllKeys() { - mDirtyRect.union(0, 0, getWidth(), getHeight()); + mInvalidatedKeys.clear(); + mInvalidateAllKeys = true; mBufferNeedsUpdate = true; invalidate(); } @@ -944,22 +943,21 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { */ @Override public void invalidateKey(Key key) { - if (key == null) - return; - mInvalidatedKey = key; + if (mInvalidateAllKeys) return; + if (key == null) return; + mInvalidatedKeys.add(key); final int x = key.mX + getPaddingLeft(); final int y = key.mY + getPaddingTop(); - mInvalidatedKeyRect.set(x, y, x + key.mWidth, y + key.mHeight); - mDirtyRect.union(mInvalidatedKeyRect); + mInvalidatedKeysRect.union(x, y, x + key.mWidth, y + key.mHeight); mBufferNeedsUpdate = true; - invalidate(mInvalidatedKeyRect); + invalidate(mInvalidatedKeysRect); } public void closing() { PointerTracker.dismissAllKeyPreviews(); cancelAllMessages(); - mDirtyRect.union(0, 0, getWidth(), getHeight()); + mInvalidateAllKeys = true; requestLayout(); } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java deleted file mode 100644 index 762039625..000000000 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2008 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.keyboard; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.Theme; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Align; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; - -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder; -import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SubtypeSwitcher; -import com.android.inputmethod.latin.Utils; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Locale; - -// TODO: We should remove this class -public class LatinKeyboard extends Keyboard { - private static final int SPACE_LED_LENGTH_PERCENT = 80; - - private final Resources mRes; - private final Theme mTheme; - private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - - /* Space key and its icons, drawables and colors. */ - private final Key mSpaceKey; - private final Drawable mSpaceIcon; - private final boolean mAutoCorrectionSpacebarLedEnabled; - private final Drawable mAutoCorrectionSpacebarLedIcon; - private final int mSpacebarTextColor; - private final int mSpacebarTextShadowColor; - private float mSpacebarTextFadeFactor = 0.0f; - private final HashMap<Integer, BitmapDrawable> mSpaceDrawableCache = - new HashMap<Integer, BitmapDrawable>(); - private final boolean mIsSpacebarTriggeringPopupByLongPress; - - /* Shortcut key and its icons if available */ - private final Key mShortcutKey; - private final Drawable mEnabledShortcutIcon; - private final Drawable mDisabledShortcutIcon; - - // Height in space key the language name will be drawn. (proportional to space key height) - public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f; - // If the full language name needs to be smaller than this value to be drawn on space key, - // its short language name will be used instead. - private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f; - - private static final String SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "small"; - private static final String MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR = "medium"; - - private LatinKeyboard(Context context, LatinKeyboardParams params) { - super(params); - mRes = context.getResources(); - mTheme = context.getTheme(); - - // The index of space key is available only after Keyboard constructor has finished. - mSpaceKey = params.mSpaceKey; - mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon() : null; - - mShortcutKey = params.mShortcutKey; - mEnabledShortcutIcon = (mShortcutKey != null) ? mShortcutKey.getIcon() : null; - final int longPressSpaceKeyTimeout = - mRes.getInteger(R.integer.config_long_press_space_key_timeout); - mIsSpacebarTriggeringPopupByLongPress = (longPressSpaceKeyTimeout > 0); - - final TypedArray a = context.obtainStyledAttributes( - null, R.styleable.LatinKeyboard, R.attr.latinKeyboardStyle, R.style.LatinKeyboard); - mAutoCorrectionSpacebarLedEnabled = a.getBoolean( - R.styleable.LatinKeyboard_autoCorrectionSpacebarLedEnabled, false); - mAutoCorrectionSpacebarLedIcon = a.getDrawable( - R.styleable.LatinKeyboard_autoCorrectionSpacebarLedIcon); - mDisabledShortcutIcon = a.getDrawable(R.styleable.LatinKeyboard_disabledShortcutIcon); - mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboard_spacebarTextColor, 0); - mSpacebarTextShadowColor = a.getColor( - R.styleable.LatinKeyboard_spacebarTextShadowColor, 0); - a.recycle(); - } - - private static class LatinKeyboardParams extends KeyboardParams { - public Key mSpaceKey = null; - public Key mShortcutKey = null; - - @Override - public void onAddKey(Key key) { - super.onAddKey(key); - - switch (key.mCode) { - case Keyboard.CODE_SPACE: - mSpaceKey = key; - break; - case Keyboard.CODE_SHORTCUT: - mShortcutKey = key; - break; - } - } - } - - public static class Builder extends KeyboardBuilder<LatinKeyboardParams> { - public Builder(Context context) { - super(context, new LatinKeyboardParams()); - } - - @Override - public Builder load(KeyboardId id) { - super.load(id); - return this; - } - - @Override - public LatinKeyboard build() { - return new LatinKeyboard(mContext, mParams); - } - } - - public void setSpacebarTextFadeFactor(float fadeFactor, KeyboardView view) { - mSpacebarTextFadeFactor = fadeFactor; - updateSpacebarForLocale(false); - if (view != null) - view.invalidateKey(mSpaceKey); - } - - private static int getSpacebarTextColor(int color, float fadeFactor) { - final int newColor = Color.argb((int)(Color.alpha(color) * fadeFactor), - Color.red(color), Color.green(color), Color.blue(color)); - return newColor; - } - - public void updateShortcutKey(boolean available, KeyboardView view) { - if (mShortcutKey == null) - return; - mShortcutKey.setEnabled(available); - mShortcutKey.setIcon(available ? mEnabledShortcutIcon : mDisabledShortcutIcon); - if (view != null) - view.invalidateKey(mShortcutKey); - } - - public boolean needsAutoCorrectionSpacebarLed() { - return mAutoCorrectionSpacebarLedEnabled; - } - - /** - * @return a key which should be invalidated. - */ - public Key onAutoCorrectionStateChanged(boolean isAutoCorrection) { - updateSpacebarForLocale(isAutoCorrection); - return mSpaceKey; - } - - @Override - public CharSequence adjustLabelCase(CharSequence label) { - if (isAlphaKeyboard() && isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) - && label.length() < 3 && Character.isLowerCase(label.charAt(0))) { - return label.toString().toUpperCase(mId.mLocale); - } - return label; - } - - private void updateSpacebarForLocale(boolean isAutoCorrection) { - if (mSpaceKey == null) return; - final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); - if (imm == null) return; - // The "..." popup hint for triggering something by a long-pressing the spacebar - final boolean shouldShowInputMethodPicker = mIsSpacebarTriggeringPopupByLongPress - && Utils.hasMultipleEnabledIMEsOrSubtypes(imm, true /* include aux subtypes */); - mSpaceKey.setNeedsSpecialPopupHint(shouldShowInputMethodPicker); - // If application locales are explicitly selected. - if (mSubtypeSwitcher.needsToDisplayLanguage(mId.mLocale)) { - mSpaceKey.setIcon(getSpaceDrawable(mId.mLocale, isAutoCorrection)); - } else if (isAutoCorrection) { - mSpaceKey.setIcon(getSpaceDrawable(null, true)); - } else { - mSpaceKey.setIcon(mSpaceIcon); - } - } - - // Compute width of text with specified text size using paint. - private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) { - paint.setTextSize(textSize); - paint.getTextBounds(text, 0, text.length(), bounds); - return bounds.width(); - } - - // Layout local language name and left and right arrow on spacebar. - private static String layoutSpacebar(Paint paint, Locale locale, int width, - float origTextSize) { - final Rect bounds = new Rect(); - - // Estimate appropriate language name text size to fit in maxTextWidth. - String language = Utils.getFullDisplayName(locale, true); - int textWidth = getTextWidth(paint, language, origTextSize, bounds); - // Assuming text width and text size are proportional to each other. - float textSize = origTextSize * Math.min(width / textWidth, 1.0f); - // allow variable text size - textWidth = getTextWidth(paint, language, textSize, bounds); - // If text size goes too small or text does not fit, use middle or short name - final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) - || (textWidth > width); - - final boolean useShortName; - if (useMiddleName) { - language = Utils.getMiddleDisplayLanguage(locale); - textWidth = getTextWidth(paint, language, origTextSize, bounds); - textSize = origTextSize * Math.min(width / textWidth, 1.0f); - useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) - || (textWidth > width); - } else { - useShortName = false; - } - - if (useShortName) { - language = Utils.getShortDisplayLanguage(locale); - textWidth = getTextWidth(paint, language, origTextSize, bounds); - textSize = origTextSize * Math.min(width / textWidth, 1.0f); - } - paint.setTextSize(textSize); - - return language; - } - - private BitmapDrawable getSpaceDrawable(Locale locale, boolean isAutoCorrection) { - final Integer hashCode = Arrays.hashCode( - new Object[] { locale, isAutoCorrection, mSpacebarTextFadeFactor }); - final BitmapDrawable cached = mSpaceDrawableCache.get(hashCode); - if (cached != null) { - return cached; - } - final BitmapDrawable drawable = new BitmapDrawable(mRes, drawSpacebar( - locale, isAutoCorrection, mSpacebarTextFadeFactor)); - mSpaceDrawableCache.put(hashCode, drawable); - return drawable; - } - - private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection, - float textFadeFactor) { - final int width = mSpaceKey.mWidth; - final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight; - final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(buffer); - final Resources res = mRes; - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - - // If application locales are explicitly selected. - if (inputLocale != null) { - final Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setTextAlign(Align.CENTER); - - final String textSizeOfLanguageOnSpacebar = res.getString( - R.string.config_text_size_of_language_on_spacebar, - SMALL_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR); - final int textStyle; - final int defaultTextSize; - if (MEDIUM_TEXT_SIZE_OF_LANGUAGE_ON_SPACEBAR.equals(textSizeOfLanguageOnSpacebar)) { - textStyle = android.R.style.TextAppearance_Medium; - defaultTextSize = 18; - } else { - textStyle = android.R.style.TextAppearance_Small; - defaultTextSize = 14; - } - - final String language = layoutSpacebar(paint, inputLocale, width, getTextSizeFromTheme( - mTheme, textStyle, defaultTextSize)); - - // Draw language text with shadow - // In case there is no space icon, we will place the language text at the center of - // spacebar. - final float descent = paint.descent(); - final float textHeight = -paint.ascent() + descent; - final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE - : height / 2 + textHeight / 2; - paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor)); - canvas.drawText(language, width / 2, baseline - descent - 1, paint); - paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor)); - canvas.drawText(language, width / 2, baseline - descent, paint); - } - - // Draw the spacebar icon at the bottom - if (isAutoCorrection) { - final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; - final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - mAutoCorrectionSpacebarLedIcon.setBounds(x, y, x + iconWidth, y + iconHeight); - mAutoCorrectionSpacebarLedIcon.draw(canvas); - } else if (mSpaceIcon != null) { - final int iconWidth = mSpaceIcon.getIntrinsicWidth(); - final int iconHeight = mSpaceIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight); - mSpaceIcon.draw(canvas); - } - return buffer; - } - - @Override - public int[] getNearestKeys(int x, int y) { - // Avoid dead pixels at edges of the keyboard - return super.getNearestKeys(Math.max(0, Math.min(x, mOccupiedWidth - 1)), - Math.max(0, Math.min(y, mOccupiedHeight - 1))); - } - - private static final int[] ATTR_TEXT_SIZE = { android.R.attr.textSize }; - - public static int getTextSizeFromTheme(Theme theme, int style, int defValue) { - final TypedArray a = theme.obtainStyledAttributes(style, ATTR_TEXT_SIZE); - final int textSize = a.getDimensionPixelSize(a.getResourceId(0, 0), defValue); - a.recycle(); - return textSize; - } -} diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 6ce3876b6..97f4d07d9 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -16,21 +16,28 @@ package com.android.inputmethod.keyboard; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.pm.PackageManager; -import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; import android.os.Message; -import android.os.SystemClock; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; -import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; import android.widget.PopupWindow; import com.android.inputmethod.accessibility.AccessibilityUtils; @@ -38,11 +45,17 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; +import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; +import com.android.inputmethod.latin.StringUtils; +import com.android.inputmethod.latin.SubtypeUtils; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; +import java.util.Locale; import java.util.WeakHashMap; /** @@ -56,45 +69,72 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke SuddenJumpingTouchEventHandler.ProcessMotionEvent { private static final String TAG = LatinKeyboardView.class.getSimpleName(); - private static final boolean ENABLE_CAPSLOCK_BY_DOUBLETAP = true; + // TODO: Kill process when the usability study mode was changed. + private static final boolean ENABLE_USABILITY_STUDY_LOG = LatinImeLogger.sUsabilityStudy; - private final SuddenJumpingTouchEventHandler mTouchScreenRegulator; - - // Timing constants - private final int mKeyRepeatInterval; + /** Listener for {@link KeyboardActionListener}. */ + private KeyboardActionListener mKeyboardActionListener; - // Mini keyboard + /* Space key and its icons */ + private Key mSpaceKey; + private Drawable mSpaceIcon; + // Stuff to draw language name on spacebar. + private ValueAnimator mLanguageOnSpacebarFadeoutAnimator; + private int mFinalAlphaOfLanguageOnSpacebar; + private static final int ALPHA_OPAQUE = 255; + private boolean mNeedsToDisplayLanguage; + private Locale mSpacebarLocale; + private int mSpacebarTextAlpha; + private final float mSpacebarTextRatio; + private float mSpacebarTextSize; + private final int mSpacebarTextColor; + private final int mSpacebarTextShadowColor; + // If the full language name needs to be smaller than this value to be drawn on space key, + // its short language name will be used instead. + private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f; + // Stuff to draw auto correction LED on spacebar. + private boolean mAutoCorrectionSpacebarLedOn; + private final boolean mAutoCorrectionSpacebarLedEnabled; + private final Drawable mAutoCorrectionSpacebarLedIcon; + private static final int SPACE_LED_LENGTH_PERCENT = 80; + + // Stuff to draw altCodeWhileTyping keys. + private ValueAnimator mAltCodeKeyWhileTypingFadeoutAnimator; + private ValueAnimator mAltCodeKeyWhileTypingFadeinAnimator; + private int mAltCodeKeyWhileTypingAnimAlpha; + + // More keys keyboard private PopupWindow mMoreKeysWindow; private MoreKeysPanel mMoreKeysPanel; private int mMoreKeysPanelPointerTrackerId; private final WeakHashMap<Key, MoreKeysPanel> mMoreKeysPanelCache = new WeakHashMap<Key, MoreKeysPanel>(); + private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint; - /** Listener for {@link KeyboardActionListener}. */ - private KeyboardActionListener mKeyboardActionListener; - - private final boolean mHasDistinctMultitouch; - private int mOldPointerCount = 1; - private int mOldKeyIndex; + private final PointerTrackerParams mPointerTrackerParams; + private final boolean mIsSpacebarTriggeringPopupByLongPress; + private final SuddenJumpingTouchEventHandler mTouchScreenRegulator; - private final boolean mConfigShowMiniKeyboardAtTouchedPoint; protected KeyDetector mKeyDetector; + private boolean mHasDistinctMultitouch; + private int mOldPointerCount = 1; + private Key mOldKey; - // To detect double tap. - protected GestureDetector mGestureDetector; - - private final KeyTimerHandler mKeyTimerHandler = new KeyTimerHandler(this); + private final KeyTimerHandler mKeyTimerHandler; private static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardView> implements TimerProxy { private static final int MSG_REPEAT_KEY = 1; private static final int MSG_LONGPRESS_KEY = 2; - private static final int MSG_IGNORE_DOUBLE_TAP = 3; + private static final int MSG_DOUBLE_TAP = 3; + private static final int MSG_TYPING_STATE_EXPIRED = 4; + private final KeyTimerParams mParams; private boolean mInKeyRepeat; - public KeyTimerHandler(LatinKeyboardView outerInstance) { + public KeyTimerHandler(LatinKeyboardView outerInstance, KeyTimerParams params) { super(outerInstance); + mParams = params; } @Override @@ -103,19 +143,39 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final PointerTracker tracker = (PointerTracker) msg.obj; switch (msg.what) { case MSG_REPEAT_KEY: - tracker.onRepeatKey(msg.arg1); - startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, msg.arg1, tracker); + tracker.onRepeatKey(tracker.getKey()); + startKeyRepeatTimer(tracker, mParams.mKeyRepeatInterval); break; case MSG_LONGPRESS_KEY: - keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker); + if (tracker != null) { + keyboardView.openMoreKeysKeyboardIfRequired(tracker.getKey(), tracker); + } else { + KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1); + } + break; + case MSG_TYPING_STATE_EXPIRED: + final ValueAnimator fadeout = keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator; + if (fadeout != null && fadeout.isStarted()) { + fadeout.cancel(); + } + // TODO: Start the fade in animation with an initial value that is the same as the + // final value when the above fade out animation gets cancelled. + final ValueAnimator fadein = keyboardView.mAltCodeKeyWhileTypingFadeinAnimator; + if (fadein != null && !fadein.isStarted()) { + fadein.start(); + } break; } } + private void startKeyRepeatTimer(PointerTracker tracker, long delay) { + sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, tracker), delay); + } + @Override - public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) { + public void startKeyRepeatTimer(PointerTracker tracker) { mInKeyRepeat = true; - sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay); + startKeyRepeatTimer(tracker, mParams.mKeyRepeatStartTimeout); } public void cancelKeyRepeatTimer() { @@ -128,9 +188,49 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } @Override - public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) { + public void startLongPressTimer(int code) { cancelLongPressTimer(); - sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay); + final int delay; + switch (code) { + case Keyboard.CODE_SHIFT: + delay = mParams.mLongPressShiftKeyTimeout; + break; + default: + delay = 0; + break; + } + if (delay > 0) { + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, code, 0), delay); + } + } + + @Override + public void startLongPressTimer(PointerTracker tracker) { + cancelLongPressTimer(); + if (tracker != null) { + final Key key = tracker.getKey(); + final int delay; + switch (key.mCode) { + case Keyboard.CODE_SHIFT: + delay = mParams.mLongPressShiftKeyTimeout; + break; + case Keyboard.CODE_SPACE: + delay = mParams.mLongPressSpaceKeyTimeout; + break; + default: + if (KeyboardSwitcher.getInstance().isInMomentarySwitchState()) { + // We use longer timeout for sliding finger input started from the symbols + // mode key. + delay = mParams.mLongPressKeyTimeout * 3; + } else { + delay = mParams.mLongPressKeyTimeout; + } + break; + } + if (delay > 0) { + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); + } + } } @Override @@ -139,19 +239,52 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } @Override - public void cancelKeyTimers() { - cancelKeyRepeatTimer(); - cancelLongPressTimer(); - removeMessages(MSG_IGNORE_DOUBLE_TAP); + public void startTypingStateTimer() { + final boolean isTyping = isTypingState(); + removeMessages(MSG_TYPING_STATE_EXPIRED); + sendMessageDelayed( + obtainMessage(MSG_TYPING_STATE_EXPIRED), mParams.mIgnoreAltCodeKeyTimeout); + final LatinKeyboardView keyboardView = getOuterInstance(); + if (isTyping) { + return; + } + final ValueAnimator fadein = keyboardView.mAltCodeKeyWhileTypingFadeinAnimator; + if (fadein != null && fadein.isStarted()) { + fadein.cancel(); + } + // TODO: Start the fade out animation with an initial value that is the same as the + // final value when the above fade in animation gets cancelled. + final ValueAnimator fadeout = keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator; + if (fadeout != null && !fadeout.isStarted()) { + fadeout.start(); + } } - public void startIgnoringDoubleTap() { - sendMessageDelayed(obtainMessage(MSG_IGNORE_DOUBLE_TAP), + @Override + public boolean isTypingState() { + return hasMessages(MSG_TYPING_STATE_EXPIRED); + } + + @Override + public void startDoubleTapTimer() { + sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP), ViewConfiguration.getDoubleTapTimeout()); } - public boolean isIgnoringDoubleTap() { - return hasMessages(MSG_IGNORE_DOUBLE_TAP); + @Override + public void cancelDoubleTapTimer() { + removeMessages(MSG_DOUBLE_TAP); + } + + @Override + public boolean isInDoubleTapTimeout() { + return hasMessages(MSG_DOUBLE_TAP); + } + + @Override + public void cancelKeyTimers() { + cancelKeyRepeatTimer(); + cancelLongPressTimer(); } public void cancelAllMessages() { @@ -159,52 +292,64 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } - private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener { - private boolean mProcessingShiftDoubleTapEvent = false; + public static class PointerTrackerParams { + public final boolean mSlidingKeyInputEnabled; + public final int mTouchNoiseThresholdTime; + public final float mTouchNoiseThresholdDistance; - @Override - public boolean onDoubleTap(MotionEvent firstDown) { - final Keyboard keyboard = getKeyboard(); - if (ENABLE_CAPSLOCK_BY_DOUBLETAP && keyboard instanceof LatinKeyboard - && ((LatinKeyboard) keyboard).isAlphaKeyboard()) { - final int pointerIndex = firstDown.getActionIndex(); - final int id = firstDown.getPointerId(pointerIndex); - final PointerTracker tracker = getPointerTracker(id); - // If the first down event is on shift key. - if (tracker.isOnShiftKey((int) firstDown.getX(), (int) firstDown.getY())) { - mProcessingShiftDoubleTapEvent = true; - return true; - } - } - mProcessingShiftDoubleTapEvent = false; - return false; + public static final PointerTrackerParams DEFAULT = new PointerTrackerParams(); + + private PointerTrackerParams() { + mSlidingKeyInputEnabled = false; + mTouchNoiseThresholdTime =0; + mTouchNoiseThresholdDistance = 0; } - @Override - public boolean onDoubleTapEvent(MotionEvent secondTap) { - if (mProcessingShiftDoubleTapEvent - && secondTap.getAction() == MotionEvent.ACTION_DOWN) { - final MotionEvent secondDown = secondTap; - final int pointerIndex = secondDown.getActionIndex(); - final int id = secondDown.getPointerId(pointerIndex); - final PointerTracker tracker = getPointerTracker(id); - // If the second down event is also on shift key. - if (tracker.isOnShiftKey((int) secondDown.getX(), (int) secondDown.getY())) { - // Detected a double tap on shift key. If we are in the ignoring double tap - // mode, it means we have already turned off caps lock in - // {@link KeyboardSwitcher#onReleaseShift} . - onDoubleTapShiftKey(tracker, mKeyTimerHandler.isIgnoringDoubleTap()); - return true; - } - // Otherwise these events should not be handled as double tap. - mProcessingShiftDoubleTapEvent = false; - } - return mProcessingShiftDoubleTapEvent; + public PointerTrackerParams(TypedArray latinKeyboardViewAttr) { + mSlidingKeyInputEnabled = latinKeyboardViewAttr.getBoolean( + R.styleable.LatinKeyboardView_slidingKeyInputEnable, false); + mTouchNoiseThresholdTime = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_touchNoiseThresholdTime, 0); + mTouchNoiseThresholdDistance = latinKeyboardViewAttr.getDimension( + R.styleable.LatinKeyboardView_touchNoiseThresholdDistance, 0); + } + } + + static class KeyTimerParams { + public final int mKeyRepeatStartTimeout; + public final int mKeyRepeatInterval; + public final int mLongPressKeyTimeout; + public final int mLongPressShiftKeyTimeout; + public final int mLongPressSpaceKeyTimeout; + public final int mIgnoreAltCodeKeyTimeout; + + KeyTimerParams() { + mKeyRepeatStartTimeout = 0; + mKeyRepeatInterval = 0; + mLongPressKeyTimeout = 0; + mLongPressShiftKeyTimeout = 0; + mLongPressSpaceKeyTimeout = 0; + mIgnoreAltCodeKeyTimeout = 0; + } + + public KeyTimerParams(TypedArray latinKeyboardViewAttr) { + mKeyRepeatStartTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_keyRepeatStartTimeout, 0); + mKeyRepeatInterval = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_keyRepeatInterval, 0); + mLongPressKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressKeyTimeout, 0); + mLongPressShiftKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0); + mLongPressSpaceKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressSpaceKeyTimeout, 0); + mIgnoreAltCodeKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_ignoreAltCodeKeyTimeout, 0); } } public LatinKeyboardView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.keyboardViewStyle); + this(context, attrs, R.attr.latinKeyboardViewStyle); } public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) { @@ -212,27 +357,104 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mTouchScreenRegulator = new SuddenJumpingTouchEventHandler(getContext(), this); - final Resources res = getResources(); - mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean( - R.bool.config_show_mini_keyboard_at_touched_point); - final float keyHysteresisDistance = res.getDimension(R.dimen.key_hysteresis_distance); - mKeyDetector = new KeyDetector(keyHysteresisDistance); - - final boolean ignoreMultitouch = true; - mGestureDetector = new GestureDetector( - getContext(), new DoubleTapListener(), null, ignoreMultitouch); - mGestureDetector.setIsLongpressEnabled(false); - mHasDistinctMultitouch = context.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); - mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); - PointerTracker.init(mHasDistinctMultitouch, getContext()); + PointerTracker.init(mHasDistinctMultitouch); + + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView); + mAutoCorrectionSpacebarLedEnabled = a.getBoolean( + R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedEnabled, false); + mAutoCorrectionSpacebarLedIcon = a.getDrawable( + R.styleable.LatinKeyboardView_autoCorrectionSpacebarLedIcon); + mSpacebarTextRatio = a.getFraction(R.styleable.LatinKeyboardView_spacebarTextRatio, + 1000, 1000, 1) / 1000.0f; + mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0); + mSpacebarTextShadowColor = a.getColor( + R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0); + final int languageOnSpacebarFadeoutAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_languageOnSpacebarFadeoutAnimator, 0); + final int altCodeKeyWhileTypingFadeoutAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeoutAnimator, 0); + final int altCodeKeyWhileTypingFadeinAnimatorResId = a.getResourceId( + R.styleable.LatinKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); + + final KeyTimerParams keyTimerParams = new KeyTimerParams(a); + mPointerTrackerParams = new PointerTrackerParams(a); + mIsSpacebarTriggeringPopupByLongPress = (keyTimerParams.mLongPressSpaceKeyTimeout > 0); + + final float keyHysteresisDistance = a.getDimension( + R.styleable.LatinKeyboardView_keyHysteresisDistance, 0); + mKeyDetector = new KeyDetector(keyHysteresisDistance); + mKeyTimerHandler = new KeyTimerHandler(this, keyTimerParams); + mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean( + R.styleable.LatinKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false); + a.recycle(); + + PointerTracker.setParameters(mPointerTrackerParams); + + final ValueAnimator animator = loadValueAnimator(languageOnSpacebarFadeoutAnimatorResId); + if (animator != null) { + animator.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mSpacebarTextAlpha = (Integer)animation.getAnimatedValue(); + invalidateKey(mSpaceKey); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + mFinalAlphaOfLanguageOnSpacebar = (Integer)valueAnimator.getAnimatedValue(); + } + }); + // In order to get the final value of animator. + animator.end(); + } + mLanguageOnSpacebarFadeoutAnimator = animator; + + final ValueAnimator fadeout = loadValueAnimator(altCodeKeyWhileTypingFadeoutAnimatorResId); + if (fadeout != null) { + fadeout.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mAltCodeKeyWhileTypingAnimAlpha = (Integer)animation.getAnimatedValue(); + updateAltCodeKeyWhileTyping(); + } + }); + fadeout.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + } + }); + } + mAltCodeKeyWhileTypingFadeoutAnimator = fadeout; + + final ValueAnimator fadein = loadValueAnimator(altCodeKeyWhileTypingFadeinAnimatorResId); + if (fadein != null) { + fadein.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mAltCodeKeyWhileTypingAnimAlpha = (Integer)animation.getAnimatedValue(); + updateAltCodeKeyWhileTyping(); + } + }); + fadein.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator a) { + final ValueAnimator valueAnimator = (ValueAnimator)a; + } + }); + } + mAltCodeKeyWhileTypingFadeinAnimator = fadein; } - public void startIgnoringDoubleTap() { - if (ENABLE_CAPSLOCK_BY_DOUBLETAP) - mKeyTimerHandler.startIgnoringDoubleTap(); + private ValueAnimator loadValueAnimator(int resId) { + if (resId == 0) return null; + return (ValueAnimator)AnimatorInflater.loadAnimator(getContext(), resId); } public void setKeyboardActionListener(KeyboardActionListener listener) { @@ -264,20 +486,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return mKeyTimerHandler; } - @Override - public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) { - final Keyboard keyboard = getKeyboard(); - if (keyboard instanceof LatinKeyboard) { - final LatinKeyboard latinKeyboard = (LatinKeyboard)keyboard; - if (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard()) { - // Phone and number keyboard never shows popup preview. - super.setKeyPreviewPopupEnabled(false, delay); - return; - } - } - super.setKeyPreviewPopupEnabled(previewEnabled, delay); - } - /** * Attaches a keyboard to this view. The keyboard can be switched at any time and the * view will re-layout itself to accommodate the keyboard. @@ -296,6 +504,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke PointerTracker.setKeyDetector(mKeyDetector); mTouchScreenRegulator.setKeyboard(keyboard); mMoreKeysPanelCache.clear(); + + mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE); + mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet) : null; + final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; + mSpacebarTextSize = keyHeight * mSpacebarTextRatio; + mSpacebarLocale = keyboard.mId.mLocale; + mSpacebarTextAlpha = ALPHA_OPAQUE; + mAltCodeKeyWhileTypingAnimAlpha = ALPHA_OPAQUE; } /** @@ -306,6 +522,10 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return mHasDistinctMultitouch; } + public void setDistinctMultitouch(boolean hasDistinctMultitouch) { + mHasDistinctMultitouch = hasDistinctMultitouch; + } + /** * When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key * codes for adjacent keys. When disabled, only the primary key code will be @@ -329,7 +549,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke super.cancelAllMessages(); } - private boolean openMiniKeyboardIfRequired(int keyIndex, PointerTracker tracker) { + private boolean openMoreKeysKeyboardIfRequired(Key parentKey, PointerTracker tracker) { // Check if we have a popup layout specified first. if (mMoreKeysLayout == 0) { return false; @@ -338,22 +558,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // Check if we are already displaying popup panel. if (mMoreKeysPanel != null) return false; - final Key parentKey = tracker.getKey(keyIndex); if (parentKey == null) return false; return onLongPress(parentKey, tracker); } - private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker, - final boolean ignore) { - // When shift key is double tapped, the first tap is correctly processed as usual tap. And - // the second tap is treated as this double tap event, so that we need not mark tracker - // calling setAlreadyProcessed() nor remove the tracker from mPointerQueue. - final int primaryCode = ignore ? Keyboard.CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY - : Keyboard.CODE_CAPSLOCK; - invokeCodeInput(primaryCode); - } - // This default implementation returns a more keys panel. protected MoreKeysPanel onCreateMoreKeysPanel(Key parentKey) { if (parentKey.mMoreKeys == null) @@ -363,28 +572,19 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke if (container == null) throw new NullPointerException(); - final MiniKeyboardView miniKeyboardView = - (MiniKeyboardView)container.findViewById(R.id.mini_keyboard_view); + final MoreKeysKeyboardView moreKeysKeyboardView = + (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); final Keyboard parentKeyboard = getKeyboard(); - final Keyboard miniKeyboard = new MiniKeyboard.Builder( + final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder( this, parentKeyboard.mMoreKeysTemplate, parentKey, parentKeyboard).build(); - miniKeyboardView.setKeyboard(miniKeyboard); + moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - return miniKeyboardView; - } - - public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboard oldKeyboard) { - final Keyboard keyboard = getKeyboard(); - // We should not set text fade factor to the keyboard which does not display the language on - // its spacebar. - if (keyboard instanceof LatinKeyboard && keyboard == oldKeyboard) { - ((LatinKeyboard)keyboard).setSpacebarTextFadeFactor(fadeFactor, this); - } + return moreKeysKeyboardView; } /** - * Called when a key is long pressed. By default this will open mini keyboard associated + * Called when a key is long pressed. By default this will open more keys keyboard associated * with this key. * @param parentKey the key that was long pressed * @param tracker the pointer tracker which pressed the parent key @@ -393,49 +593,37 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke */ protected boolean onLongPress(Key parentKey, PointerTracker tracker) { final int primaryCode = parentKey.mCode; - final Keyboard keyboard = getKeyboard(); - if (keyboard instanceof LatinKeyboard) { - final LatinKeyboard latinKeyboard = (LatinKeyboard) keyboard; - if (primaryCode == Keyboard.CODE_DIGIT0 && latinKeyboard.isPhoneKeyboard()) { - tracker.onLongPressed(); - // Long pressing on 0 in phone number keypad gives you a '+'. - invokeCodeInput(Keyboard.CODE_PLUS); - invokeReleaseKey(primaryCode); - return true; - } - if (primaryCode == Keyboard.CODE_SHIFT && latinKeyboard.isAlphaKeyboard()) { - tracker.onLongPressed(); - invokeCodeInput(Keyboard.CODE_CAPSLOCK); - invokeReleaseKey(primaryCode); - return true; - } + if (parentKey.hasEmbeddedMoreKey()) { + final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]); + tracker.onLongPressed(); + invokeCodeInput(embeddedCode); + invokeReleaseKey(primaryCode); + KeyboardSwitcher.getInstance().hapticAndAudioFeedback(primaryCode); + return true; } - if (primaryCode == Keyboard.CODE_SETTINGS || primaryCode == Keyboard.CODE_SPACE) { - // Both long pressing settings key and space key invoke IME switcher dialog. + if (primaryCode == Keyboard.CODE_SPACE || primaryCode == Keyboard.CODE_LANGUAGE_SWITCH) { + // Long pressing the space key invokes IME switcher dialog. if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) { tracker.onLongPressed(); invokeReleaseKey(primaryCode); return true; - } else { - return openMoreKeysPanel(parentKey, tracker); } - } else { - return openMoreKeysPanel(parentKey, tracker); } + return openMoreKeysPanel(parentKey, tracker); } private boolean invokeCustomRequest(int code) { - return getKeyboardActionListener().onCustomRequest(code); + return mKeyboardActionListener.onCustomRequest(code); } private void invokeCodeInput(int primaryCode) { - getKeyboardActionListener().onCodeInput(primaryCode, null, + mKeyboardActionListener.onCodeInput(primaryCode, KeyboardActionListener.NOT_A_TOUCH_COORDINATE, KeyboardActionListener.NOT_A_TOUCH_COORDINATE); } private void invokeReleaseKey(int primaryCode) { - getKeyboardActionListener().onRelease(primaryCode, false); + mKeyboardActionListener.onReleaseKey(primaryCode, false); } private boolean openMoreKeysPanel(Key parentKey, PointerTracker tracker) { @@ -449,30 +637,24 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke if (mMoreKeysWindow == null) { mMoreKeysWindow = new PopupWindow(getContext()); mMoreKeysWindow.setBackgroundDrawable(null); - mMoreKeysWindow.setAnimationStyle(R.style.MiniKeyboardAnimation); + mMoreKeysWindow.setAnimationStyle(R.style.MoreKeysKeyboardAnimation); } mMoreKeysPanel = moreKeysPanel; mMoreKeysPanelPointerTrackerId = tracker.mPointerId; final Keyboard keyboard = getKeyboard(); - moreKeysPanel.setShifted(keyboard.isShiftedOrShiftLocked()); - final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX() + final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint) ? tracker.getLastX() : parentKey.mX + parentKey.mWidth / 2; final int pointY = parentKey.mY - keyboard.mVerticalGap; moreKeysPanel.showMoreKeysPanel( - this, this, pointX, pointY, mMoreKeysWindow, getKeyboardActionListener()); + this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener); final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); - tracker.onShowMoreKeysPanel( - translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel); + tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel); dimEntireKeyboard(true); return true; } - private PointerTracker getPointerTracker(final int id) { - return PointerTracker.getPointerTracker(id, this); - } - public boolean isInSlidingKeyInput() { if (mMoreKeysPanel != null) { return true; @@ -508,14 +690,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke return true; } - // Gesture detector must be enabled only when mini-keyboard is not on the screen. - if (mMoreKeysPanel == null && mGestureDetector != null - && mGestureDetector.onTouchEvent(me)) { - PointerTracker.dismissAllKeyPreviews(); - mKeyTimerHandler.cancelKeyTimers(); - return true; - } - final long eventTime = me.getEventTime(); final int index = me.getActionIndex(); final int id = me.getPointerId(index); @@ -527,9 +701,37 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke x = (int)me.getX(index); y = (int)me.getY(index); } + if (ENABLE_USABILITY_STUDY_LOG) { + final String eventTag; + switch (action) { + case MotionEvent.ACTION_UP: + eventTag = "[Up]"; + break; + case MotionEvent.ACTION_DOWN: + eventTag = "[Down]"; + break; + case MotionEvent.ACTION_POINTER_UP: + eventTag = "[PointerUp]"; + break; + case MotionEvent.ACTION_POINTER_DOWN: + eventTag = "[PointerDown]"; + break; + case MotionEvent.ACTION_MOVE: // Skip this as being logged below + eventTag = ""; + break; + default: + eventTag = "[Action" + action + "]"; + break; + } + if (!TextUtils.isEmpty(eventTag)) { + UsabilityStudyLogUtils.getInstance().write( + eventTag + eventTime + "," + id + "," + x + "," + y + "," + + me.getSize(index) + "," + me.getPressure(index)); + } + } if (mKeyTimerHandler.isInKeyRepeat()) { - final PointerTracker tracker = getPointerTracker(id); + final PointerTracker tracker = PointerTracker.getPointerTracker(id, this); // Key repeating timer will be canceled if 2 or more keys are in action, and current // event (UP or DOWN) is non-modifier key. if (pointerCount > 1 && !tracker.isModifier()) { @@ -543,13 +745,13 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // multi-touch panel. if (nonDistinctMultitouch) { // Use only main (id=0) pointer tracker. - PointerTracker tracker = getPointerTracker(0); + final PointerTracker tracker = PointerTracker.getPointerTracker(0, this); if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. // Send a down event for the latest pointer if the key is different from the // previous key. - final int newKeyIndex = tracker.getKeyIndexOn(x, y); - if (mOldKeyIndex != newKeyIndex) { + final Key newKey = tracker.getKeyOn(x, y); + if (mOldKey != newKey) { tracker.onDownEvent(x, y, eventTime, this); if (action == MotionEvent.ACTION_UP) tracker.onUpEvent(x, y, eventTime); @@ -559,7 +761,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // Send an up event for the last pointer. final int lastX = tracker.getLastX(); final int lastY = tracker.getLastY(); - mOldKeyIndex = tracker.getKeyIndexOn(lastX, lastY); + mOldKey = tracker.getKeyOn(lastX, lastY); tracker.onUpEvent(lastX, lastY, eventTime); } else if (pointerCount == 1 && oldPointerCount == 1) { tracker.processMotionEvent(action, x, y, eventTime, this); @@ -572,7 +774,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke if (action == MotionEvent.ACTION_MOVE) { for (int i = 0; i < pointerCount; i++) { - final PointerTracker tracker = getPointerTracker(me.getPointerId(i)); + final PointerTracker tracker = PointerTracker.getPointerTracker( + me.getPointerId(i), this); final int px, py; if (mMoreKeysPanel != null && tracker.mPointerId == mMoreKeysPanelPointerTrackerId) { @@ -583,9 +786,15 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke py = (int)me.getY(i); } tracker.onMoveEvent(px, py, eventTime); + if (ENABLE_USABILITY_STUDY_LOG) { + UsabilityStudyLogUtils.getInstance().write("[Move]" + eventTime + "," + + me.getPointerId(i) + "," + px + "," + py + "," + + me.getSize(i) + "," + me.getPressure(i)); + } } } else { - getPointerTracker(id).processMotionEvent(action, x, y, eventTime, this); + final PointerTracker tracker = PointerTracker.getPointerTracker(id, this); + tracker.processMotionEvent(action, x, y, eventTime, this); } return true; @@ -623,7 +832,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke super.draw(c); tryGC = false; } catch (OutOfMemoryError e) { - tryGC = Utils.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e); + tryGC = Utils.GCUtils.getInstance().tryGCOrWait(TAG, e); } } } @@ -634,17 +843,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke VoiceProxy.getInstance().onAttachedToWindow(); } - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { - final PointerTracker tracker = getPointerTracker(0); - return AccessibleKeyboardViewProxy.getInstance().dispatchPopulateAccessibilityEvent( - event, tracker) || super.dispatchPopulateAccessibilityEvent(event); - } - - return super.dispatchPopulateAccessibilityEvent(event); - } - /** * Receives hover events from the input framework. This method overrides * View.dispatchHoverEvent(MotionEvent) on SDK version ICS or higher. On @@ -654,13 +852,162 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * @return {@code true} if the event was handled by the view, {@code false} * otherwise */ + //Should not annotate @override public boolean dispatchHoverEvent(MotionEvent event) { if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { - final PointerTracker tracker = getPointerTracker(0); + final PointerTracker tracker = PointerTracker.getPointerTracker(0, this); return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent(event, tracker); } // Reflection doesn't support calling superclass methods. return false; } + + public void updateShortcutKey(boolean available) { + final Keyboard keyboard = getKeyboard(); + if (keyboard == null) return; + final Key shortcutKey = keyboard.getKey(Keyboard.CODE_SHORTCUT); + if (shortcutKey == null) return; + shortcutKey.setEnabled(available); + invalidateKey(shortcutKey); + } + + private void updateAltCodeKeyWhileTyping() { + final Keyboard keyboard = getKeyboard(); + if (keyboard == null) return; + for (final Key key : keyboard.mAltCodeKeysWhileTyping) { + invalidateKey(key); + } + } + + public void startDisplayLanguageOnSpacebar(boolean subtypeChanged, + boolean needsToDisplayLanguage) { + final ValueAnimator animator = mLanguageOnSpacebarFadeoutAnimator; + if (animator != null) { + animator.cancel(); + } + mNeedsToDisplayLanguage = needsToDisplayLanguage; + if (animator == null) { + mNeedsToDisplayLanguage = false; + } else { + if (subtypeChanged && needsToDisplayLanguage) { + mSpacebarTextAlpha = ALPHA_OPAQUE; + animator.start(); + } else { + mSpacebarTextAlpha = mFinalAlphaOfLanguageOnSpacebar; + } + } + invalidateKey(mSpaceKey); + } + + public void updateAutoCorrectionState(boolean isAutoCorrection) { + if (!mAutoCorrectionSpacebarLedEnabled) return; + mAutoCorrectionSpacebarLedOn = isAutoCorrection; + invalidateKey(mSpaceKey); + } + + @Override + protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { + if (key.altCodeWhileTyping() && key.isEnabled()) { + params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; + } + if (key.mCode == Keyboard.CODE_SPACE) { + drawSpacebar(key, canvas, paint); + + // Whether space key needs to show the "..." popup hint for special purposes + if (mIsSpacebarTriggeringPopupByLongPress + && SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes( + true /* include aux subtypes */)) { + drawKeyPopupHint(key, canvas, paint, params); + } + } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) { + super.onDrawKeyTopVisuals(key, canvas, paint, params); + if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { + drawKeyPopupHint(key, canvas, paint, params); + } + } else { + super.onDrawKeyTopVisuals(key, canvas, paint, params); + } + } + + // Compute width of text with specified text size using paint. + private int getTextWidth(Paint paint, String text, float textSize) { + paint.setTextSize(textSize); + return (int)getLabelWidth(text, paint); + } + + // Layout locale language name on spacebar. + private String layoutLanguageOnSpacebar(Paint paint, Locale locale, int width, + float origTextSize) { + paint.setTextAlign(Align.CENTER); + paint.setTypeface(Typeface.DEFAULT); + // Estimate appropriate language name text size to fit in maxTextWidth. + String language = StringUtils.getFullDisplayName(locale, true); + int textWidth = getTextWidth(paint, language, origTextSize); + // Assuming text width and text size are proportional to each other. + float textSize = origTextSize * Math.min(width / textWidth, 1.0f); + // allow variable text size + textWidth = getTextWidth(paint, language, textSize); + // If text size goes too small or text does not fit, use middle or short name + final boolean useMiddleName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) + || (textWidth > width); + + final boolean useShortName; + if (useMiddleName) { + language = StringUtils.getMiddleDisplayLanguage(locale); + textWidth = getTextWidth(paint, language, origTextSize); + textSize = origTextSize * Math.min(width / textWidth, 1.0f); + useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) + || (textWidth > width); + } else { + useShortName = false; + } + + if (useShortName) { + language = StringUtils.getShortDisplayLanguage(locale); + textWidth = getTextWidth(paint, language, origTextSize); + textSize = origTextSize * Math.min(width / textWidth, 1.0f); + } + paint.setTextSize(textSize); + + return language; + } + + private void drawSpacebar(Key key, Canvas canvas, Paint paint) { + final int width = key.mWidth; + final int height = key.mHeight; + + // If input subtypes are explicitly selected. + if (mNeedsToDisplayLanguage) { + final String language = layoutLanguageOnSpacebar(paint, mSpacebarLocale, width, + mSpacebarTextSize); + // Draw language text with shadow + // In case there is no space icon, we will place the language text at the center of + // spacebar. + final float descent = paint.descent(); + final float textHeight = -paint.ascent() + descent; + final float baseline = height / 2 + textHeight / 2; + paint.setColor(mSpacebarTextShadowColor); + paint.setAlpha(mSpacebarTextAlpha); + canvas.drawText(language, width / 2, baseline - descent - 1, paint); + paint.setColor(mSpacebarTextColor); + paint.setAlpha(mSpacebarTextAlpha); + canvas.drawText(language, width / 2, baseline - descent, paint); + } + + // Draw the spacebar icon at the bottom + if (mAutoCorrectionSpacebarLedOn) { + final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; + final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight); + } else if (mSpaceIcon != null) { + final int iconWidth = mSpaceIcon.getIntrinsicWidth(); + final int iconHeight = mSpaceIcon.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight); + } + } } diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java deleted file mode 100644 index ac9290bfd..000000000 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2011 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.keyboard; - -import android.graphics.Paint; - -import com.android.inputmethod.keyboard.internal.KeyboardBuilder; -import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.keyboard.internal.MoreKeySpecParser; -import com.android.inputmethod.latin.R; - -public class MiniKeyboard extends Keyboard { - private final int mDefaultKeyCoordX; - - private MiniKeyboard(Builder.MiniKeyboardParams params) { - super(params); - mDefaultKeyCoordX = params.getDefaultKeyCoordX() + params.mDefaultKeyWidth / 2; - } - - public int getDefaultCoordX() { - return mDefaultKeyCoordX; - } - - public static class Builder extends KeyboardBuilder<Builder.MiniKeyboardParams> { - private final CharSequence[] mMoreKeys; - - public static class MiniKeyboardParams extends KeyboardParams { - /* package */int mTopRowAdjustment; - public int mNumRows; - public int mNumColumns; - public int mLeftKeys; - public int mRightKeys; // includes default key. - - public MiniKeyboardParams() { - super(); - } - - /* package for test */MiniKeyboardParams(int numKeys, int maxColumns, int keyWidth, - int rowHeight, int coordXInParent, int parentKeyboardWidth) { - super(); - setParameters(numKeys, maxColumns, keyWidth, rowHeight, coordXInParent, - parentKeyboardWidth); - } - - /** - * Set keyboard parameters of mini keyboard. - * - * @param numKeys number of keys in this mini keyboard. - * @param maxColumns number of maximum columns of this mini keyboard. - * @param keyWidth mini keyboard key width in pixel, including horizontal gap. - * @param rowHeight mini keyboard row height in pixel, including vertical gap. - * @param coordXInParent coordinate x of the popup key in parent keyboard. - * @param parentKeyboardWidth parent keyboard width in pixel. - */ - public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight, - int coordXInParent, int parentKeyboardWidth) { - if (parentKeyboardWidth / keyWidth < maxColumns) { - throw new IllegalArgumentException( - "Keyboard is too small to hold mini keyboard: " + parentKeyboardWidth - + " " + keyWidth + " " + maxColumns); - } - mDefaultKeyWidth = keyWidth; - mDefaultRowHeight = rowHeight; - - final int numRows = (numKeys + maxColumns - 1) / maxColumns; - mNumRows = numRows; - final int numColumns = getOptimizedColumns(numKeys, maxColumns); - mNumColumns = numColumns; - - final int numLeftKeys = (numColumns - 1) / 2; - final int numRightKeys = numColumns - numLeftKeys; // including default key. - final int maxLeftKeys = coordXInParent / keyWidth; - final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) - / keyWidth); - int leftKeys, rightKeys; - if (numLeftKeys > maxLeftKeys) { - leftKeys = maxLeftKeys; - rightKeys = numColumns - maxLeftKeys; - } else if (numRightKeys > maxRightKeys) { - leftKeys = numColumns - maxRightKeys; - rightKeys = maxRightKeys; - } else { - leftKeys = numLeftKeys; - rightKeys = numRightKeys; - } - // Shift right if the left edge of mini keyboard is on the edge of parent keyboard - // unless the parent key is on the left edge. - if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) { - leftKeys--; - rightKeys++; - } - // Shift left if the right edge of mini keyboard is on the edge of parent keyboard - // unless the parent key is on the right edge. - if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) { - leftKeys++; - rightKeys--; - } - mLeftKeys = leftKeys; - mRightKeys = rightKeys; - - // Centering of the top row. - final boolean onEdge = (leftKeys == 0 || rightKeys == 1); - if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) { - mTopRowAdjustment = 0; - } else if (mLeftKeys < mRightKeys - 1) { - mTopRowAdjustment = 1; - } else { - mTopRowAdjustment = -1; - } - - mBaseWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth; - // Need to subtract the bottom row's gutter only. - mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap - + mTopPadding + mBottomPadding; - } - - // Return key position according to column count (0 is default). - /* package */int getColumnPos(int n) { - final int col = n % mNumColumns; - if (col == 0) { - // default position. - return 0; - } - int pos = 0; - int right = 1; // include default position key. - int left = 0; - int i = 0; - while (true) { - // Assign right key if available. - if (right < mRightKeys) { - pos = right; - right++; - i++; - } - if (i >= col) - break; - // Assign left key if available. - if (left < mLeftKeys) { - left++; - pos = -left; - i++; - } - if (i >= col) - break; - } - return pos; - } - - private static int getTopRowEmptySlots(int numKeys, int numColumns) { - final int remainingKeys = numKeys % numColumns; - if (remainingKeys == 0) { - return 0; - } else { - return numColumns - remainingKeys; - } - } - - private int getOptimizedColumns(int numKeys, int maxColumns) { - int numColumns = Math.min(numKeys, maxColumns); - while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) { - numColumns--; - } - return numColumns; - } - - public int getDefaultKeyCoordX() { - return mLeftKeys * mDefaultKeyWidth; - } - - public int getX(int n, int row) { - final int x = getColumnPos(n) * mDefaultKeyWidth + getDefaultKeyCoordX(); - if (isTopRow(row)) { - return x + mTopRowAdjustment * (mDefaultKeyWidth / 2); - } - return x; - } - - public int getY(int row) { - return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding; - } - - public void markAsEdgeKey(Key key, int row) { - if (row == 0) - key.markAsTopEdge(this); - if (isTopRow(row)) - key.markAsBottomEdge(this); - } - - private boolean isTopRow(int rowCount) { - return rowCount == mNumRows - 1; - } - } - - public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) { - super(view.getContext(), new MiniKeyboardParams()); - load(parentKeyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId)); - - // TODO: Mini keyboard's vertical gap is currently calculated heuristically. - // Should revise the algorithm. - mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2; - mParams.mIsRtlKeyboard = parentKeyboard.mIsRtlKeyboard; - mMoreKeys = parentKey.mMoreKeys; - - final int previewWidth = view.mKeyPreviewDrawParams.mPreviewBackgroundWidth; - final int previewHeight = view.mKeyPreviewDrawParams.mPreviewBackgroundHeight; - final int width, height; - // Use pre-computed width and height if these values are available and mini keyboard - // has only one key to mitigate visual flicker between key preview and mini keyboard. - if (view.isKeyPreviewPopupEnabled() && mMoreKeys.length == 1 && previewWidth > 0 - && previewHeight > 0) { - width = previewWidth; - height = previewHeight + mParams.mVerticalGap; - } else { - width = getMaxKeyWidth(view, parentKey.mMoreKeys, mParams.mDefaultKeyWidth); - height = parentKeyboard.mMostCommonKeyHeight; - } - mParams.setParameters(mMoreKeys.length, parentKey.mMaxMoreKeysColumn, width, height, - parentKey.mX + (mParams.mDefaultKeyWidth - width) / 2, view.getMeasuredWidth()); - } - - private static int getMaxKeyWidth(KeyboardView view, CharSequence[] moreKeys, - int minKeyWidth) { - final int padding = (int) view.getContext().getResources() - .getDimension(R.dimen.mini_keyboard_key_horizontal_padding); - Paint paint = null; - int maxWidth = minKeyWidth; - for (CharSequence moreKeySpec : moreKeys) { - final CharSequence label = MoreKeySpecParser.getLabel(moreKeySpec.toString()); - // If the label is single letter, minKeyWidth is enough to hold - // the label. - if (label != null && label.length() > 1) { - if (paint == null) { - paint = new Paint(); - paint.setAntiAlias(true); - } - final int width = (int)view.getDefaultLabelWidth(label, paint) + padding; - if (maxWidth < width) { - maxWidth = width; - } - } - } - return maxWidth; - } - - @Override - public MiniKeyboard build() { - final MiniKeyboardParams params = mParams; - for (int n = 0; n < mMoreKeys.length; n++) { - final String moreKeySpec = mMoreKeys[n].toString(); - final int row = n / params.mNumColumns; - final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row), - params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight); - params.markAsEdgeKey(key, row); - params.onAddKey(key); - } - return new MiniKeyboard(params); - } - } -} diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java index d20204611..6c8d02016 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java @@ -16,8 +16,6 @@ package com.android.inputmethod.keyboard; -import java.util.List; - public class MoreKeysDetector extends KeyDetector { private final int mSlideAllowanceSquare; private final int mSlideAllowanceSquareTop; @@ -41,24 +39,41 @@ public class MoreKeysDetector extends KeyDetector { } @Override - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; + public void getNearbyCodes(int x, int y, final int[] allCodes) { final int touchX = getTouchX(x); final int touchY = getTouchY(y); - int nearestIndex = NOT_A_KEY; + Key nearestKey = null; int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; - final int keyCount = keys.size(); - for (int index = 0; index < keyCount; index++) { - final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); + for (final Key key : getKeyboard().mKeys) { + final int dist = key.squaredDistanceToEdge(touchX, touchY); if (dist < nearestDist) { - nearestIndex = index; + nearestKey = key; nearestDist = dist; } } - if (allCodes != null && nearestIndex != NOT_A_KEY) - allCodes[0] = keys.get(nearestIndex).mCode; - return nearestIndex; + if (nearestKey != null) { + allCodes[0] = nearestKey.mCode; + } else { + allCodes[0] = NOT_A_CODE; + } + } + + @Override + public Key detectHitKey(int x, int y) { + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + + Key nearestKey = null; + int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; + for (final Key key : getKeyboard().mKeys) { + final int dist = key.squaredDistanceToEdge(touchX, touchY); + if (dist < nearestDist) { + nearestKey = key; + nearestDist = dist; + } + } + return nearestKey; } -}
\ No newline at end of file +} diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java new file mode 100644 index 000000000..904a81de4 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2011 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.keyboard; + +import android.graphics.Paint; +import android.graphics.drawable.Drawable; + +import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; + +public class MoreKeysKeyboard extends Keyboard { + private final int mDefaultKeyCoordX; + + MoreKeysKeyboard(Builder.MoreKeysKeyboardParams params) { + super(params); + mDefaultKeyCoordX = params.getDefaultKeyCoordX() + params.mDefaultKeyWidth / 2; + } + + public int getDefaultCoordX() { + return mDefaultKeyCoordX; + } + + public static class Builder extends Keyboard.Builder<Builder.MoreKeysKeyboardParams> { + private final Key mParentKey; + private final Drawable mDivider; + + private static final float LABEL_PADDING_RATIO = 0.2f; + private static final float DIVIDER_RATIO = 0.2f; + + public static class MoreKeysKeyboardParams extends Keyboard.Params { + public boolean mIsFixedOrder; + /* package */int mTopRowAdjustment; + public int mNumRows; + public int mNumColumns; + public int mTopKeys; + public int mLeftKeys; + public int mRightKeys; // includes default key. + public int mDividerWidth; + public int mColumnWidth; + + public MoreKeysKeyboardParams() { + super(); + } + + /** + * Set keyboard parameters of more keys keyboard. + * + * @param numKeys number of keys in this more keys keyboard. + * @param maxColumns number of maximum columns of this more keys keyboard. + * @param keyWidth more keys keyboard key width in pixel, including horizontal gap. + * @param rowHeight more keys keyboard row height in pixel, including vertical gap. + * @param coordXInParent coordinate x of the key preview in parent keyboard. + * @param parentKeyboardWidth parent keyboard width in pixel. + * @param isFixedColumnOrder if true, more keys should be laid out in fixed order. + * @param dividerWidth width of divider, zero for no dividers. + */ + public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight, + int coordXInParent, int parentKeyboardWidth, boolean isFixedColumnOrder, + int dividerWidth) { + mIsFixedOrder = isFixedColumnOrder; + if (parentKeyboardWidth / keyWidth < maxColumns) { + throw new IllegalArgumentException( + "Keyboard is too small to hold more keys keyboard: " + + parentKeyboardWidth + " " + keyWidth + " " + maxColumns); + } + mDefaultKeyWidth = keyWidth; + mDefaultRowHeight = rowHeight; + + final int numRows = (numKeys + maxColumns - 1) / maxColumns; + mNumRows = numRows; + final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns) + : getOptimizedColumns(numKeys, maxColumns); + mNumColumns = numColumns; + final int topKeys = numKeys % numColumns; + mTopKeys = topKeys == 0 ? numColumns : topKeys; + + final int numLeftKeys = (numColumns - 1) / 2; + final int numRightKeys = numColumns - numLeftKeys; // including default key. + // Maximum number of keys we can layout both side of the parent key + final int maxLeftKeys = coordXInParent / keyWidth; + final int maxRightKeys = (parentKeyboardWidth - coordXInParent) / keyWidth; + int leftKeys, rightKeys; + if (numLeftKeys > maxLeftKeys) { + leftKeys = maxLeftKeys; + rightKeys = numColumns - leftKeys; + } else if (numRightKeys > maxRightKeys + 1) { + rightKeys = maxRightKeys + 1; // include default key + leftKeys = numColumns - rightKeys; + } else { + leftKeys = numLeftKeys; + rightKeys = numRightKeys; + } + // If the left keys fill the left side of the parent key, entire more keys keyboard + // should be shifted to the right unless the parent key is on the left edge. + if (maxLeftKeys == leftKeys && leftKeys > 0) { + leftKeys--; + rightKeys++; + } + // If the right keys fill the right side of the parent key, entire more keys + // should be shifted to the left unless the parent key is on the right edge. + if (maxRightKeys == rightKeys - 1 && rightKeys > 1) { + leftKeys++; + rightKeys--; + } + mLeftKeys = leftKeys; + mRightKeys = rightKeys; + + // Adjustment of the top row. + mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment() + : getAutoOrderTopRowAdjustment(); + mDividerWidth = dividerWidth; + mColumnWidth = mDefaultKeyWidth + mDividerWidth; + mBaseWidth = mOccupiedWidth = mNumColumns * mColumnWidth - mDividerWidth; + // Need to subtract the bottom row's gutter only. + mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap + + mTopPadding + mBottomPadding; + } + + private int getFixedOrderTopRowAdjustment() { + if (mNumRows == 1 || mTopKeys % 2 == 1 || mTopKeys == mNumColumns + || mLeftKeys == 0 || mRightKeys == 1) { + return 0; + } + return -1; + } + + private int getAutoOrderTopRowAdjustment() { + if (mNumRows == 1 || mTopKeys == 1 || mNumColumns % 2 == mTopKeys % 2 + || mLeftKeys == 0 || mRightKeys == 1) { + return 0; + } + return -1; + } + + // Return key position according to column count (0 is default). + /* package */int getColumnPos(int n) { + return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n); + } + + private int getFixedOrderColumnPos(int n) { + final int col = n % mNumColumns; + final int row = n / mNumColumns; + if (!isTopRow(row)) { + return col - mLeftKeys; + } + final int rightSideKeys = mTopKeys / 2; + final int leftSideKeys = mTopKeys - (rightSideKeys + 1); + final int pos = col - leftSideKeys; + final int numLeftKeys = mLeftKeys + mTopRowAdjustment; + final int numRightKeys = mRightKeys - 1; + if (numRightKeys >= rightSideKeys && numLeftKeys >= leftSideKeys) { + return pos; + } else if (numRightKeys < rightSideKeys) { + return pos - (rightSideKeys - numRightKeys); + } else { // numLeftKeys < leftSideKeys + return pos + (leftSideKeys - numLeftKeys); + } + } + + private int getAutomaticColumnPos(int n) { + final int col = n % mNumColumns; + final int row = n / mNumColumns; + int leftKeys = mLeftKeys; + if (isTopRow(row)) { + leftKeys += mTopRowAdjustment; + } + if (col == 0) { + // default position. + return 0; + } + + int pos = 0; + int right = 1; // include default position key. + int left = 0; + int i = 0; + while (true) { + // Assign right key if available. + if (right < mRightKeys) { + pos = right; + right++; + i++; + } + if (i >= col) + break; + // Assign left key if available. + if (left < leftKeys) { + left++; + pos = -left; + i++; + } + if (i >= col) + break; + } + return pos; + } + + private static int getTopRowEmptySlots(int numKeys, int numColumns) { + final int remainings = numKeys % numColumns; + return remainings == 0 ? 0 : numColumns - remainings; + } + + private int getOptimizedColumns(int numKeys, int maxColumns) { + int numColumns = Math.min(numKeys, maxColumns); + while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) { + numColumns--; + } + return numColumns; + } + + public int getDefaultKeyCoordX() { + return mLeftKeys * mColumnWidth; + } + + public int getX(int n, int row) { + final int x = getColumnPos(n) * mColumnWidth + getDefaultKeyCoordX(); + if (isTopRow(row)) { + return x + mTopRowAdjustment * (mColumnWidth / 2); + } + return x; + } + + public int getY(int row) { + return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding; + } + + public void markAsEdgeKey(Key key, int row) { + if (row == 0) + key.markAsTopEdge(this); + if (isTopRow(row)) + key.markAsBottomEdge(this); + } + + private boolean isTopRow(int rowCount) { + return mNumRows > 1 && rowCount == mNumRows - 1; + } + } + + public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) { + super(view.getContext(), new MoreKeysKeyboardParams()); + load(xmlId, parentKeyboard.mId); + + // TODO: More keys keyboard's vertical gap is currently calculated heuristically. + // Should revise the algorithm. + mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2; + mParentKey = parentKey; + + final int previewWidth = view.mKeyPreviewDrawParams.mPreviewBackgroundWidth; + final int previewHeight = view.mKeyPreviewDrawParams.mPreviewBackgroundHeight; + final int width, height; + // Use pre-computed width and height if these values are available and more keys + // keyboard has only one key to mitigate visual flicker between key preview and more + // keys keyboard. + final boolean validKeyPreview = view.isKeyPreviewPopupEnabled() + && !parentKey.noKeyPreview() && (previewWidth > 0) && (previewHeight > 0); + final boolean singleMoreKeyWithPreview = validKeyPreview + && parentKey.mMoreKeys.length == 1; + if (singleMoreKeyWithPreview) { + width = previewWidth; + height = previewHeight + mParams.mVerticalGap; + } else { + width = getMaxKeyWidth(view, parentKey, mParams.mDefaultKeyWidth); + height = parentKeyboard.mMostCommonKeyHeight; + } + final int dividerWidth; + if (parentKey.needsDividersInMoreKeys()) { + mDivider = mResources.getDrawable(R.drawable.more_keys_divider); + // TODO: Drawable itself should have an alpha value. + mDivider.setAlpha(128); + dividerWidth = (int)(width * DIVIDER_RATIO); + } else { + mDivider = null; + dividerWidth = 0; + } + mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(), + width, height, parentKey.mX + parentKey.mWidth / 2, view.getMeasuredWidth(), + parentKey.isFixedColumnOrderMoreKeys(), dividerWidth); + } + + private static int getMaxKeyWidth(KeyboardView view, Key parentKey, int minKeyWidth) { + final int padding = (int)(view.getResources() + .getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding) + + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0)); + Paint paint = null; + int maxWidth = minKeyWidth; + for (String moreKeySpec : parentKey.mMoreKeys) { + final String label = KeySpecParser.getLabel(moreKeySpec); + // If the label is single letter, minKeyWidth is enough to hold the label. + if (label != null && StringUtils.codePointCount(label) > 1) { + if (paint == null) { + paint = new Paint(); + paint.setAntiAlias(true); + } + final int width = (int)view.getDefaultLabelWidth(label, paint) + padding; + if (maxWidth < width) { + maxWidth = width; + } + } + } + return maxWidth; + } + + private static class MoreKeyDivider extends Key.Spacer { + private final Drawable mIcon; + + public MoreKeyDivider(MoreKeysKeyboardParams params, Drawable icon, int x, int y) { + super(params, x, y, params.mDividerWidth, params.mDefaultRowHeight); + mIcon = icon; + } + + @Override + public Drawable getIcon(KeyboardIconsSet iconSet) { + // KeyboardIconsSet is unused. Use the icon that has been passed to the constructor. + return mIcon; + } + } + + @Override + public MoreKeysKeyboard build() { + final MoreKeysKeyboardParams params = mParams; + // moreKeyFlags == 0 means that the rendered text size will be determined by its + // label's code point count. + final int moreKeyFlags = mParentKey.hasLabelsInMoreKeys() ? 0 + : Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO; + final String[] moreKeys = mParentKey.mMoreKeys; + for (int n = 0; n < moreKeys.length; n++) { + final String moreKeySpec = moreKeys[n]; + final int row = n / params.mNumColumns; + final int x = params.getX(n, row); + final int y = params.getY(row); + final Key key = new Key(mResources, params, moreKeySpec, x, y, + params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags); + params.markAsEdgeKey(key, row); + params.onAddKey(key); + + final int pos = params.getColumnPos(n); + // The "pos" value represents the offset from the default position. Negative means + // left of the default position. + if (params.mDividerWidth > 0 && pos != 0) { + final int dividerX = (pos > 0) ? x - params.mDividerWidth + : x + params.mDefaultKeyWidth; + final Key divider = new MoreKeyDivider(params, mDivider, dividerX, y); + params.onAddKey(divider); + } + } + return new MoreKeysKeyboard(params); + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 471fb4e2a..2495b5472 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -28,10 +28,10 @@ import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.latin.R; /** - * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting - * key presses and touch movements. + * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and + * detecting key presses and touch movements. */ -public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { +public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel { private final int[] mCoordinates = new int[2]; private final KeyDetector mKeyDetector; @@ -43,11 +43,11 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter(); - private final KeyboardActionListener mMiniKeyboardListener = + private final KeyboardActionListener mMoreKeysKeyboardListener = new KeyboardActionListener.Adapter() { @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { - mListener.onCodeInput(primaryCode, keyCodes, x, y); + public void onCodeInput(int primaryCode, int x, int y) { + mListener.onCodeInput(primaryCode, x, y); } @Override @@ -61,25 +61,26 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { } @Override - public void onPress(int primaryCode, boolean withSliding) { - mListener.onPress(primaryCode, withSliding); + public void onPressKey(int primaryCode) { + mListener.onPressKey(primaryCode); } + @Override - public void onRelease(int primaryCode, boolean withSliding) { - mListener.onRelease(primaryCode, withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding) { + mListener.onReleaseKey(primaryCode, withSliding); } }; - public MiniKeyboardView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.miniKeyboardViewStyle); + public MoreKeysKeyboardView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.moreKeysKeyboardViewStyle); } - public MiniKeyboardView(Context context, AttributeSet attrs, int defStyle) { + public MoreKeysKeyboardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources res = context.getResources(); mKeyDetector = new MoreKeysDetector( - res.getDimension(R.dimen.mini_keyboard_slide_allowance)); + res.getDimension(R.dimen.more_keys_keyboard_slide_allowance)); setKeyPreviewPopupEnabled(false, 0); } @@ -109,7 +110,7 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { @Override public KeyboardActionListener getKeyboardActionListener() { - return mMiniKeyboardListener; + return mMoreKeysKeyboardListener; } @Override @@ -124,26 +125,18 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { @Override public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) { - // Mini keyboard needs no pop-up key preview displayed, so we pass always false with a + // More keys keyboard needs no pop-up key preview displayed, so we pass always false with a // delay of 0. The delay does not matter actually since the popup is not shown anyway. super.setKeyPreviewPopupEnabled(false, 0); } @Override - public void setShifted(boolean shifted) { - final Keyboard keyboard = getKeyboard(); - if (keyboard.setShifted(shifted)) { - invalidateAllKeys(); - } - } - - @Override public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY, PopupWindow window, KeyboardActionListener listener) { mController = controller; mListener = listener; final View container = (View)getParent(); - final MiniKeyboard pane = (MiniKeyboard)getKeyboard(); + final MoreKeysKeyboard pane = (MoreKeysKeyboard)getKeyboard(); final int defaultCoordX = pane.getDefaultCoordX(); // The coordinates of panel's left-top corner in parentView's coordinate system. final int x = pointX - defaultCoordX - container.getPaddingLeft() diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java index 6314a99db..f9a196d24 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysPanel.java @@ -24,8 +24,6 @@ public interface MoreKeysPanel extends PointerTracker.KeyEventHandler { public boolean dismissMoreKeysPanel(); } - public void setShifted(boolean shifted); - /** * Show more keys panel. * diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 198e06aab..ec9081681 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -16,19 +16,15 @@ package com.android.inputmethod.keyboard; -import android.content.Context; -import android.content.res.Resources; +import android.os.SystemClock; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; public class PointerTracker { private static final String TAG = PointerTracker.class.getSimpleName(); @@ -67,40 +63,51 @@ public class PointerTracker { public interface DrawingProxy extends MoreKeysPanel.Controller { public void invalidateKey(Key key); public TextView inflateKeyPreviewText(); - public void showKeyPreview(int keyIndex, PointerTracker tracker); - public void cancelShowKeyPreview(PointerTracker tracker); + public void showKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker); } public interface TimerProxy { - public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker); - public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker); + public void startTypingStateTimer(); + public boolean isTypingState(); + public void startKeyRepeatTimer(PointerTracker tracker); + public void startLongPressTimer(PointerTracker tracker); + public void startLongPressTimer(int code); public void cancelLongPressTimer(); + public void startDoubleTapTimer(); + public void cancelDoubleTapTimer(); + public boolean isInDoubleTapTimeout(); public void cancelKeyTimers(); public static class Adapter implements TimerProxy { @Override - public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {} + public void startTypingStateTimer() {} @Override - public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {} + public boolean isTypingState() { return false; } + @Override + public void startKeyRepeatTimer(PointerTracker tracker) {} + @Override + public void startLongPressTimer(PointerTracker tracker) {} + @Override + public void startLongPressTimer(int code) {} @Override public void cancelLongPressTimer() {} @Override + public void startDoubleTapTimer() {} + @Override + public void cancelDoubleTapTimer() {} + @Override + public boolean isInDoubleTapTimeout() { return false; } + @Override public void cancelKeyTimers() {} } } - private static KeyboardSwitcher sKeyboardSwitcher; - private static boolean sConfigSlidingKeyInputEnabled; - // Timing constants - private static int sDelayBeforeKeyRepeatStart; - private static int sLongPressKeyTimeout; - private static int sLongPressShiftKeyTimeout; - private static int sLongPressSpaceKeyTimeout; - private static int sTouchNoiseThresholdMillis; + // Parameters for pointer handling. + private static LatinKeyboardView.PointerTrackerParams sParams; private static int sTouchNoiseThresholdDistanceSquared; - private static final List<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); + private static final ArrayList<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); private static PointerTrackerQueue sPointerTrackerQueue; public final int mPointerId; @@ -111,7 +118,6 @@ public class PointerTracker { private KeyboardActionListener mListener = EMPTY_LISTENER; private Keyboard mKeyboard; - private List<Key> mKeys; private int mKeyQuarterWidthSquared; private final TextView mKeyPreviewText; @@ -119,9 +125,9 @@ public class PointerTracker { private long mDownTime; private long mUpTime; - // The current key index where this pointer is. - private int mKeyIndex = KeyDetector.NOT_A_KEY; - // The position where mKeyIndex was recognized for the first time. + // The current key where this pointer is. + private Key mCurrentKey = null; + // The position where the current key was recognized for the first time. private int mKeyX; private int mKeyY; @@ -154,29 +160,24 @@ public class PointerTracker { private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener.Adapter(); - public static void init(boolean hasDistinctMultitouch, Context context) { + public static void init(boolean hasDistinctMultitouch) { if (hasDistinctMultitouch) { sPointerTrackerQueue = new PointerTrackerQueue(); } else { sPointerTrackerQueue = null; } - final Resources res = context.getResources(); - sConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); - sDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); - sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); - sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout); - sLongPressSpaceKeyTimeout = res.getInteger(R.integer.config_long_press_space_key_timeout); - sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis); - final float touchNoiseThresholdDistance = res.getDimension( - R.dimen.config_touch_noise_threshold_distance); + setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT); + } + + public static void setParameters(LatinKeyboardView.PointerTrackerParams params) { + sParams = params; sTouchNoiseThresholdDistanceSquared = (int)( - touchNoiseThresholdDistance * touchNoiseThresholdDistance); - sKeyboardSwitcher = KeyboardSwitcher.getInstance(); + params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance); } public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { - final List<PointerTracker> trackers = sTrackers; + final ArrayList<PointerTracker> trackers = sTrackers; // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = trackers.size(); i <= id; i++) { @@ -207,7 +208,7 @@ public class PointerTracker { public static void dismissAllKeyPreviews() { for (final PointerTracker tracker : sTrackers) { - tracker.setReleasedKeyGraphics(tracker.mKeyIndex); + tracker.setReleasedKeyGraphics(tracker.mCurrentKey); } } @@ -227,15 +228,18 @@ public class PointerTracker { } // Returns true if keyboard has been changed by this callback. - private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key, boolean withSliding) { - final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode); - if (DEBUG_LISTENER) - Log.d(TAG, "onPress : " + keyCodePrintable(key.mCode) + " sliding=" + withSliding - + " ignoreModifier=" + ignoreModifierKey); - if (ignoreModifierKey) + private boolean callListenerOnPressAndCheckKeyboardLayoutChange(Key key) { + final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); + if (DEBUG_LISTENER) { + Log.d(TAG, "onPress : " + KeyDetector.printableCode(key) + + " ignoreModifier=" + ignoreModifierKey + + " enabled=" + key.isEnabled()); + } + if (ignoreModifierKey) { return false; + } if (key.isEnabled()) { - mListener.onPress(key.mCode, withSliding); + mListener.onPressKey(key.mCode); final boolean keyboardLayoutHasBeenChanged = mKeyboardLayoutHasBeenChanged; mKeyboardLayoutHasBeenChanged = false; return keyboardLayoutHasBeenChanged; @@ -245,36 +249,47 @@ public class PointerTracker { // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. - private void callListenerOnCodeInput(Key key, int primaryCode, int[] keyCodes, int x, int y) { - final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode); - if (DEBUG_LISTENER) - Log.d(TAG, "onCodeInput: " + keyCodePrintable(primaryCode) - + " codes="+ Arrays.toString(keyCodes) + " x=" + x + " y=" + y - + " ignoreModifier=" + ignoreModifierKey); - if (ignoreModifierKey) + private void callListenerOnCodeInput(Key key, int primaryCode, int x, int y) { + final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); + final int code = altersCode ? key.mAltCode : primaryCode; + if (DEBUG_LISTENER) { + Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText + + " x=" + x + " y=" + y + + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + + " enabled=" + key.isEnabled()); + } + if (ignoreModifierKey) { return; - if (key.isEnabled()) - mListener.onCodeInput(primaryCode, keyCodes, x, y); - } - - private void callListenerOnTextInput(Key key) { - if (DEBUG_LISTENER) - Log.d(TAG, "onTextInput: text=" + key.mOutputText); - if (key.isEnabled()) - mListener.onTextInput(key.mOutputText); + } + // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. + if (key.isEnabled() || altersCode) { + if (code == Keyboard.CODE_OUTPUT_TEXT) { + mListener.onTextInput(key.mOutputText); + } else if (code != Keyboard.CODE_UNSPECIFIED) { + mListener.onCodeInput(code, x, y); + } + if (!key.altCodeWhileTyping() && !key.isModifier()) { + mTimerProxy.startTypingStateTimer(); + } + } } // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. private void callListenerOnRelease(Key key, int primaryCode, boolean withSliding) { - final boolean ignoreModifierKey = mIgnoreModifierKey && isModifierCode(key.mCode); - if (DEBUG_LISTENER) - Log.d(TAG, "onRelease : " + keyCodePrintable(primaryCode) + " sliding=" - + withSliding + " ignoreModifier=" + ignoreModifierKey); - if (ignoreModifierKey) + final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier(); + if (DEBUG_LISTENER) { + Log.d(TAG, "onRelease : " + Keyboard.printableCode(primaryCode) + + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + + " enabled="+ key.isEnabled()); + } + if (ignoreModifierKey) { return; - if (key.isEnabled()) - mListener.onRelease(primaryCode, withSliding); + } + if (key.isEnabled()) { + mListener.onReleaseKey(primaryCode, withSliding); + } } private void callListenerOnCancelInput() { @@ -286,7 +301,6 @@ public class PointerTracker { private void setKeyDetectorInner(KeyDetector keyDetector) { mKeyDetector = keyDetector; mKeyboard = keyDetector.getKeyboard(); - mKeys = mKeyboard.mKeys; final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4; mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth; } @@ -295,71 +309,96 @@ public class PointerTracker { return mIsInSlidingKeyInput; } - private boolean isValidKeyIndex(int keyIndex) { - return keyIndex >= 0 && keyIndex < mKeys.size(); + public Key getKey() { + return mCurrentKey; } - public Key getKey(int keyIndex) { - return isValidKeyIndex(keyIndex) ? mKeys.get(keyIndex) : null; + public boolean isModifier() { + return mCurrentKey != null && mCurrentKey.isModifier(); } - private static boolean isModifierCode(int primaryCode) { - return primaryCode == Keyboard.CODE_SHIFT - || primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL; + public Key getKeyOn(int x, int y) { + return mKeyDetector.detectHitKey(x, y); } - private boolean isModifierInternal(int keyIndex) { - final Key key = getKey(keyIndex); - return key == null ? false : isModifierCode(key.mCode); - } + private void setReleasedKeyGraphics(Key key) { + mDrawingProxy.dismissKeyPreview(this); + if (key == null) { + return; + } - public boolean isModifier() { - return isModifierInternal(mKeyIndex); - } + // Even if the key is disabled, update the key release graphics just in case. + updateReleaseKeyGraphics(key); - private boolean isOnModifierKey(int x, int y) { - return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null)); - } + if (key.isShift()) { + for (final Key shiftKey : mKeyboard.mShiftKeys) { + if (shiftKey != key) { + updateReleaseKeyGraphics(shiftKey); + } + } + } - public boolean isOnShiftKey(int x, int y) { - final Key key = getKey(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null)); - return key != null && key.mCode == Keyboard.CODE_SHIFT; + if (key.altCodeWhileTyping()) { + final int altCode = key.mAltCode; + final Key altKey = mKeyboard.getKey(altCode); + if (altKey != null) { + updateReleaseKeyGraphics(altKey); + } + for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { + if (k != key && k.mAltCode == altCode) { + updateReleaseKeyGraphics(k); + } + } + } } - public int getKeyIndexOn(int x, int y) { - return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); - } + private void setPressedKeyGraphics(Key key) { + if (key == null) { + return; + } - private void setReleasedKeyGraphics(int keyIndex) { - mDrawingProxy.dismissKeyPreview(this); - final Key key = getKey(keyIndex); - if (key != null && key.isEnabled()) { - key.onReleased(); - mDrawingProxy.invalidateKey(key); + // Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state. + final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState(); + final boolean needsToUpdateGraphics = key.isEnabled() || altersCode; + if (!needsToUpdateGraphics) { + return; } - } - private void setPressedKeyGraphics(int keyIndex) { - final Key key = getKey(keyIndex); - if (key != null && key.isEnabled()) { - if (isKeyPreviewRequired(key)) { - mDrawingProxy.showKeyPreview(keyIndex, this); + if (!key.noKeyPreview()) { + mDrawingProxy.showKeyPreview(this); + } + updatePressKeyGraphics(key); + + if (key.isShift()) { + for (final Key shiftKey : mKeyboard.mShiftKeys) { + if (shiftKey != key) { + updatePressKeyGraphics(shiftKey); + } } - key.onPressed(); - mDrawingProxy.invalidateKey(key); } - } - // The modifier key, such as shift key, should not show its key preview. - private static boolean isKeyPreviewRequired(Key key) { - final int code = key.mCode; - // TODO: Stop hard-coding these key codes here, and add a new key attribute of a key. - if (code == Keyboard.CODE_SPACE || code == Keyboard.CODE_ENTER - || code == Keyboard.CODE_DELETE || isModifierCode(code) - || code == Keyboard.CODE_SETTINGS || code == Keyboard.CODE_SHORTCUT) { - return false; + if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) { + final int altCode = key.mAltCode; + final Key altKey = mKeyboard.getKey(altCode); + if (altKey != null) { + updatePressKeyGraphics(altKey); + } + for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) { + if (k != key && k.mAltCode == altCode) { + updatePressKeyGraphics(k); + } + } } - return true; + } + + private void updateReleaseKeyGraphics(Key key) { + key.onReleased(); + mDrawingProxy.invalidateKey(key); + } + + private void updatePressKeyGraphics(Key key) { + key.onPressed(); + mDrawingProxy.invalidateKey(key); } public int getLastX() { @@ -374,31 +413,31 @@ public class PointerTracker { return mDownTime; } - private int onDownKey(int x, int y, long eventTime) { + private Key onDownKey(int x, int y, long eventTime) { mDownTime = eventTime; return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); } - private int onMoveKeyInternal(int x, int y) { + private Key onMoveKeyInternal(int x, int y) { mLastX = x; mLastY = y; - return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); + return mKeyDetector.detectHitKey(x, y); } - private int onMoveKey(int x, int y) { + private Key onMoveKey(int x, int y) { return onMoveKeyInternal(x, y); } - private int onMoveToNewKey(int keyIndex, int x, int y) { - mKeyIndex = keyIndex; + private Key onMoveToNewKey(Key newKey, int x, int y) { + mCurrentKey = newKey; mKeyX = x; mKeyY = y; - return keyIndex; + return newKey; } - private int onUpKey(int x, int y, long eventTime) { + private Key onUpKey(int x, int y, long eventTime) { mUpTime = eventTime; - mKeyIndex = KeyDetector.NOT_A_KEY; + mCurrentKey = null; return onMoveKeyInternal(x, y); } @@ -432,7 +471,7 @@ public class PointerTracker { setKeyDetectorInner(handler.getKeyDetector()); // Naive up-to-down noise filter. final long deltaT = eventTime - mUpTime; - if (deltaT < sTouchNoiseThresholdMillis) { + if (deltaT < sParams.mTouchNoiseThresholdTime) { final int dx = x - mLastX; final int dy = y - mLastY; final int distanceSquared = (dx * dx + dy * dy); @@ -447,7 +486,8 @@ public class PointerTracker { final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { - if (isOnModifierKey(x, y)) { + final Key key = getKeyOn(x, y); + if (key != null && key.isModifier()) { // Before processing a down event of modifier key, all pointers already being // tracked should be released. queue.releaseAllPointers(eventTime); @@ -458,32 +498,35 @@ public class PointerTracker { } private void onDownEventInternal(int x, int y, long eventTime) { - int keyIndex = onDownKey(x, y, eventTime); + Key key = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding // from modifier key, or 3) this pointer's KeyDetector always allows sliding input. - mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex) + mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled + || (key != null && key.isModifier()) || mKeyDetector.alwaysAllowsSlidingInput(); mKeyboardLayoutHasBeenChanged = false; mKeyAlreadyProcessed = false; mIsRepeatableKey = false; mIsInSlidingKeyInput = false; mIgnoreModifierKey = false; - if (isValidKeyIndex(keyIndex)) { + if (key != null) { // This onPress call may have changed keyboard layout. Those cases are detected at - // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new + // {@link #setKeyboard}. In those cases, we should update key according to the new // keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false)) - keyIndex = onDownKey(x, y, eventTime); + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { + key = onDownKey(x, y, eventTime); + } - startRepeatKey(keyIndex); - startLongPressTimer(keyIndex); - setPressedKeyGraphics(keyIndex); + startRepeatKey(key); + startLongPressTimer(key); + setPressedKeyGraphics(key); } } private void startSlidingKeyInput(Key key) { - if (!mIsInSlidingKeyInput) - mIgnoreModifierKey = isModifierCode(key.mCode); + if (!mIsInSlidingKeyInput) { + mIgnoreModifierKey = key.isModifier(); + } mIsInSlidingKeyInput = true; } @@ -495,39 +538,40 @@ public class PointerTracker { final int lastX = mLastX; final int lastY = mLastY; - final int oldKeyIndex = mKeyIndex; - final Key oldKey = getKey(oldKeyIndex); - int keyIndex = onMoveKey(x, y); - if (isValidKeyIndex(keyIndex)) { + final Key oldKey = mCurrentKey; + Key key = onMoveKey(x, y); + if (key != null) { if (oldKey == null) { // The pointer has been slid in to the new key, but the finger was not on any keys. // In this case, we must call onPress() to notify that the new key is being pressed. // This onPress call may have changed keyboard layout. Those cases are detected at - // {@link #setKeyboard}. In those cases, we should update keyIndex according to the + // {@link #setKeyboard}. In those cases, we should update key according to the // new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true)) - keyIndex = onMoveKey(x, y); - onMoveToNewKey(keyIndex, x, y); - startLongPressTimer(keyIndex); - setPressedKeyGraphics(keyIndex); - } else if (isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) { + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { + key = onMoveKey(x, y); + } + onMoveToNewKey(key, x, y); + startLongPressTimer(key); + setPressedKeyGraphics(key); + } else if (isMajorEnoughMoveToBeOnNewKey(x, y, key)) { // The pointer has been slid in to the new key from the previous key, we must call // onRelease() first to notify that the previous key has been released, then call // onPress() to notify that the new key is being pressed. - setReleasedKeyGraphics(oldKeyIndex); + setReleasedKeyGraphics(oldKey); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); mTimerProxy.cancelKeyTimers(); - startRepeatKey(keyIndex); + startRepeatKey(key); if (mIsAllowedSlidingKeyInput) { // This onPress call may have changed keyboard layout. Those cases are detected - // at {@link #setKeyboard}. In those cases, we should update keyIndex according + // at {@link #setKeyboard}. In those cases, we should update key according // to the new keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true)) - keyIndex = onMoveKey(x, y); - onMoveToNewKey(keyIndex, x, y); - startLongPressTimer(keyIndex); - setPressedKeyGraphics(keyIndex); + if (callListenerOnPressAndCheckKeyboardLayoutChange(key)) { + key = onMoveKey(x, y); + } + onMoveToNewKey(key, x, y); + startLongPressTimer(key); + setPressedKeyGraphics(key); } else { // HACK: On some devices, quick successive touches may be translated to sudden // move by touch panel firmware. This hack detects the case and translates the @@ -543,20 +587,20 @@ public class PointerTracker { onDownEventInternal(x, y, eventTime); } else { mKeyAlreadyProcessed = true; - setReleasedKeyGraphics(oldKeyIndex); + setReleasedKeyGraphics(oldKey); } } } } else { - if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) { + if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, key)) { // The pointer has been slid out from the previous key, we must call onRelease() to // notify that the previous key has been released. - setReleasedKeyGraphics(oldKeyIndex); + setReleasedKeyGraphics(oldKey); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); mTimerProxy.cancelLongPressTimer(); if (mIsAllowedSlidingKeyInput) { - onMoveToNewKey(keyIndex, x, y); + onMoveToNewKey(key, x, y); } else { mKeyAlreadyProcessed = true; } @@ -570,7 +614,7 @@ public class PointerTracker { final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { - if (isModifier()) { + if (mCurrentKey != null && mCurrentKey.isModifier()) { // Before processing an up event of modifier key, all pointers already being // tracked should be released. queue.releaseAllPointersExcept(this, eventTime); @@ -594,7 +638,6 @@ public class PointerTracker { private void onUpEventInternal(int x, int y, long eventTime) { mTimerProxy.cancelKeyTimers(); - mDrawingProxy.cancelShowKeyPreview(this); mIsInSlidingKeyInput = false; final int keyX, keyY; if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) { @@ -605,8 +648,8 @@ public class PointerTracker { keyX = mKeyX; keyY = mKeyY; } - final int keyIndex = onUpKey(keyX, keyY, eventTime); - setReleasedKeyGraphics(keyIndex); + final Key key = onUpKey(keyX, keyY, eventTime); + setReleasedKeyGraphics(key); if (mIsShowingMoreKeysPanel) { mDrawingProxy.dismissMoreKeysPanel(); mIsShowingMoreKeysPanel = false; @@ -614,19 +657,19 @@ public class PointerTracker { if (mKeyAlreadyProcessed) return; if (!mIsRepeatableKey) { - detectAndSendKey(keyIndex, keyX, keyY); + detectAndSendKey(key, keyX, keyY); } } - public void onShowMoreKeysPanel(int x, int y, long eventTime, KeyEventHandler handler) { + public void onShowMoreKeysPanel(int x, int y, KeyEventHandler handler) { onLongPressed(); - onDownEvent(x, y, eventTime, handler); + onDownEvent(x, y, SystemClock.uptimeMillis(), handler); mIsShowingMoreKeysPanel = true; } public void onLongPressed() { mKeyAlreadyProcessed = true; - setReleasedKeyGraphics(mKeyIndex); + setReleasedKeyGraphics(mCurrentKey); final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { queue.remove(this); @@ -647,8 +690,7 @@ public class PointerTracker { private void onCancelEventInternal() { mTimerProxy.cancelKeyTimers(); - mDrawingProxy.cancelShowKeyPreview(this); - setReleasedKeyGraphics(mKeyIndex); + setReleasedKeyGraphics(mCurrentKey); mIsInSlidingKeyInput = false; if (mIsShowingMoreKeysPanel) { mDrawingProxy.dismissMoreKeysPanel(); @@ -656,108 +698,61 @@ public class PointerTracker { } } - private void startRepeatKey(int keyIndex) { - final Key key = getKey(keyIndex); - if (key != null && key.mRepeatable) { - onRepeatKey(keyIndex); - mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, keyIndex, this); + private void startRepeatKey(Key key) { + if (key != null && key.isRepeatable()) { + onRepeatKey(key); + mTimerProxy.startKeyRepeatTimer(this); mIsRepeatableKey = true; } else { mIsRepeatableKey = false; } } - public void onRepeatKey(int keyIndex) { - Key key = getKey(keyIndex); + public void onRepeatKey(Key key) { if (key != null) { - detectAndSendKey(keyIndex, key.mX, key.mY); + detectAndSendKey(key, key.mX, key.mY); } } - private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) { - if (mKeys == null || mKeyDetector == null) + private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, Key newKey) { + if (mKeyDetector == null) throw new NullPointerException("keyboard and/or key detector not set"); - int curKey = mKeyIndex; + Key curKey = mCurrentKey; if (newKey == curKey) { return false; - } else if (isValidKeyIndex(curKey)) { - return mKeys.get(curKey).squaredDistanceToEdge(x, y) + } else if (curKey != null) { + return curKey.squaredDistanceToEdge(x, y) >= mKeyDetector.getKeyHysteresisDistanceSquared(); } else { return true; } } - private void startLongPressTimer(int keyIndex) { - Key key = getKey(keyIndex); - if (key == null) return; - if (key.mCode == Keyboard.CODE_SHIFT) { - if (sLongPressShiftKeyTimeout > 0) { - mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, keyIndex, this); - } - } else if (key.mCode == Keyboard.CODE_SPACE) { - if (sLongPressSpaceKeyTimeout > 0) { - mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, keyIndex, this); - } - } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) { - // We need not start long press timer on the key which has manual temporary upper case - // code defined and the keyboard is in manual temporary upper case mode. - return; - } else if (sKeyboardSwitcher.isInMomentarySwitchState()) { - // We use longer timeout for sliding finger input started from the symbols mode key. - mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, keyIndex, this); - } else { - mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, keyIndex, this); + private void startLongPressTimer(Key key) { + if (key != null && key.isLongPressEnabled()) { + mTimerProxy.startLongPressTimer(this); } } - private void detectAndSendKey(int index, int x, int y) { - final Key key = getKey(index); + private void detectAndSendKey(Key key, int x, int y) { if (key == null) { callListenerOnCancelInput(); return; } - if (key.mOutputText != null) { - callListenerOnTextInput(key); - callListenerOnRelease(key, key.mCode, false); - } else { - int code = key.mCode; - final int[] codes = mKeyDetector.newCodeArray(); - mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); - - // If keyboard is in manual temporary upper case state and key has manual temporary - // uppercase letter as key hint letter, alternate character code should be sent. - if (mKeyboard.isManualTemporaryUpperCase() && key.hasUppercaseLetter()) { - code = key.mHintLabel.charAt(0); - codes[0] = code; - } - // Swap the first and second values in the codes array if the primary code is not the - // first value but the second value in the array. This happens when key debouncing is - // in effect. - if (codes.length >= 2 && codes[0] != code && codes[1] == code) { - codes[1] = codes[0]; - codes[0] = code; - } - callListenerOnCodeInput(key, code, codes, x, y); - callListenerOnRelease(key, code, false); - } + int code = key.mCode; + callListenerOnCodeInput(key, code, x, y); + callListenerOnRelease(key, code, false); } private long mPreviousEventTime; private void printTouchEvent(String title, int x, int y, long eventTime) { - final int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); - final Key key = getKey(keyIndex); - final String code = (key == null) ? "----" : keyCodePrintable(key.mCode); + final Key key = mKeyDetector.detectHitKey(x, y); + final String code = KeyDetector.printableCode(key); final long delta = eventTime - mPreviousEventTime; - Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %3d(%s)", title, - (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, keyIndex, code)); + Log.d(TAG, String.format("%s%s[%d] %4d %4d %5d %s", title, + (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, delta, code)); mPreviousEventTime = eventTime; } - - private static String keyCodePrintable(int primaryCode) { - final String modifier = isModifierCode(primaryCode) ? " modifier" : ""; - return String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode) + modifier; - } } diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index 2a25d0ca7..61d75e278 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -17,20 +17,23 @@ package com.android.inputmethod.keyboard; import android.graphics.Rect; +import android.text.TextUtils; -import com.android.inputmethod.keyboard.internal.KeyboardParams.TouchPositionCorrection; -import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.keyboard.Keyboard.Params.TouchPositionCorrection; +import com.android.inputmethod.latin.JniUtils; import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class ProximityInfo { public static final int MAX_PROXIMITY_CHARS_SIZE = 16; /** Number of key widths from current touch point to search for nearest keys. */ private static float SEARCH_DISTANCE = 1.2f; - private static final int[] EMPTY_INT_ARRAY = new int[0]; + private static final Key[] EMPTY_KEY_ARRAY = new Key[0]; private final int mKeyHeight; private final int mGridWidth; @@ -41,10 +44,19 @@ public class ProximityInfo { // TODO: Find a proper name for mKeyboardMinWidth private final int mKeyboardMinWidth; private final int mKeyboardHeight; - private final int[][] mGridNeighbors; - - ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, - int keyHeight, List<Key> keys, TouchPositionCorrection touchPositionCorrection) { + private final int mMostCommonKeyWidth; + private final Key[][] mGridNeighbors; + private final String mLocaleStr; + + ProximityInfo(String localeStr, int gridWidth, int gridHeight, int minWidth, int height, + int mostCommonKeyWidth, int mostCommonKeyHeight, final Key[] keys, + TouchPositionCorrection touchPositionCorrection, + Map<Integer, List<Integer>> additionalProximityChars) { + if (TextUtils.isEmpty(localeStr)) { + mLocaleStr = ""; + } else { + mLocaleStr = localeStr; + } mGridWidth = gridWidth; mGridHeight = gridHeight; mGridSize = mGridWidth * mGridHeight; @@ -52,60 +64,69 @@ public class ProximityInfo { mCellHeight = (height + mGridHeight - 1) / mGridHeight; mKeyboardMinWidth = minWidth; mKeyboardHeight = height; - mKeyHeight = keyHeight; - mGridNeighbors = new int[mGridSize][]; + mKeyHeight = mostCommonKeyHeight; + mMostCommonKeyWidth = mostCommonKeyWidth; + mGridNeighbors = new Key[mGridSize][]; if (minWidth == 0 || height == 0) { - // No proximity required. Keyboard might be mini keyboard. + // No proximity required. Keyboard might be more keys keyboard. return; } - computeNearestNeighbors(keyWidth, keys, touchPositionCorrection); + computeNearestNeighbors( + mostCommonKeyWidth, keys, touchPositionCorrection, additionalProximityChars); } public static ProximityInfo createDummyProximityInfo() { - return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptyList(), null); + return new ProximityInfo("", 1, 1, 1, 1, 1, 1, EMPTY_KEY_ARRAY, null, + Collections.<Integer, List<Integer>> emptyMap()); } - public static ProximityInfo createSpellCheckerProximityInfo() { + public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) { final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo(); spellCheckerProximityInfo.mNativeProximityInfo = - spellCheckerProximityInfo.setProximityInfoNative( - SpellCheckerProximityInfo.ROW_SIZE, - 480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY, + spellCheckerProximityInfo.setProximityInfoNative("", + SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, (480 / 10), proximity, 0, null, null, null, null, null, null, null, null); return spellCheckerProximityInfo; } - private int mNativeProximityInfo; + private long mNativeProximityInfo; static { - Utils.loadNativeLibrary(); + JniUtils.loadNativeLibrary(); } - private native int setProximityInfoNative(int maxProximityCharsSize, int displayWidth, - int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray, + + private native long setProximityInfoNative( + String locale, int maxProximityCharsSize, int displayWidth, + int displayHeight, int gridWidth, int gridHeight, + int mostCommonKeyWidth, int[] proximityCharsArray, int keyCount, int[] keyXCoordinates, int[] keyYCoordinates, int[] keyWidths, int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii); - private native void releaseProximityInfoNative(int nativeProximityInfo); - private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth, - int keyboardHeight, List<Key> keys, - TouchPositionCorrection touchPositionCorrection) { - int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; + private native void releaseProximityInfoNative(long nativeProximityInfo); + + private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth, + int keyboardHeight, final Key[] keys, TouchPositionCorrection touchPositionCorrection) { + final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE); for (int i = 0; i < mGridSize; ++i) { - final int proximityCharsLength = gridNeighborKeyIndexes[i].length; + final int proximityCharsLength = gridNeighborKeys[i].length; for (int j = 0; j < proximityCharsLength; ++j) { proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] = - keys.get(gridNeighborKeyIndexes[i][j]).mCode; + gridNeighborKeys[i][j].mCode; } } - final int keyCount = keys.size(); + final int keyCount = keys.length; final int[] keyXCoordinates = new int[keyCount]; final int[] keyYCoordinates = new int[keyCount]; final int[] keyWidths = new int[keyCount]; final int[] keyHeights = new int[keyCount]; final int[] keyCharCodes = new int[keyCount]; + final float[] sweetSpotCenterXs; + final float[] sweetSpotCenterYs; + final float[] sweetSpotRadii; + for (int i = 0; i < keyCount; ++i) { - final Key key = keys.get(i); + final Key key = keys[i]; keyXCoordinates[i] = key.mX; keyYCoordinates[i] = key.mY; keyWidths[i] = key.mWidth; @@ -113,51 +134,40 @@ public class ProximityInfo { keyCharCodes[i] = key.mCode; } - float[] sweetSpotCenterXs = null; - float[] sweetSpotCenterYs = null; - float[] sweetSpotRadii = null; - if (touchPositionCorrection != null && touchPositionCorrection.isValid()) { sweetSpotCenterXs = new float[keyCount]; sweetSpotCenterYs = new float[keyCount]; sweetSpotRadii = new float[keyCount]; - calculateSweetSpot(keys, touchPositionCorrection, - sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); + for (int i = 0; i < keyCount; i++) { + final Key key = keys[i]; + final Rect hitBox = key.mHitBox; + final int row = hitBox.top / mKeyHeight; + if (row < touchPositionCorrection.mRadii.length) { + final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f; + final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f; + final float hitBoxWidth = hitBox.right - hitBox.left; + final float hitBoxHeight = hitBox.bottom - hitBox.top; + final float x = touchPositionCorrection.mXs[row]; + final float y = touchPositionCorrection.mYs[row]; + final float radius = touchPositionCorrection.mRadii[row]; + sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth; + sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight; + sweetSpotRadii[i] = radius * (float) Math.sqrt( + hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); + } + } + } else { + sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; } - mNativeProximityInfo = setProximityInfoNative(MAX_PROXIMITY_CHARS_SIZE, - keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray, + mNativeProximityInfo = setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, + keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, + proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); } - private void calculateSweetSpot(List<Key> keys, TouchPositionCorrection touchPositionCorrection, - float[] sweetSpotCenterXs, float[] sweetSpotCenterYs, float[] sweetSpotRadii) { - final int keyCount = keys.size(); - final float[] xs = touchPositionCorrection.mXs; - final float[] ys = touchPositionCorrection.mYs; - final float[] radii = touchPositionCorrection.mRadii; - for (int i = 0; i < keyCount; ++i) { - final Key key = keys.get(i); - final Rect hitBox = key.mHitBox; - final int row = hitBox.top / mKeyHeight; - if (row < radii.length) { - final float hitBoxCenterX = (hitBox.left + hitBox.right) * 0.5f; - final float hitBoxCenterY = (hitBox.top + hitBox.bottom) * 0.5f; - final float hitBoxWidth = hitBox.right - hitBox.left; - final float hitBoxHeight = hitBox.bottom - hitBox.top; - final float x = xs[row]; - final float y = ys[row]; - final float radius = radii[row]; - sweetSpotCenterXs[i] = hitBoxCenterX + x * hitBoxWidth; - sweetSpotCenterYs[i] = hitBoxCenterY + y * hitBoxHeight; - sweetSpotRadii[i] = radius - * (float)Math.sqrt(hitBoxWidth * hitBoxWidth + hitBoxHeight * hitBoxHeight); - } - } - } - - public int getNativeProximityInfo() { + public long getNativeProximityInfo() { return mNativeProximityInfo; } @@ -173,12 +183,17 @@ public class ProximityInfo { } } - private void computeNearestNeighbors(int defaultWidth, List<Key> keys, - TouchPositionCorrection touchPositionCorrection) { + private void computeNearestNeighbors(int defaultWidth, final Key[] keys, + TouchPositionCorrection touchPositionCorrection, + Map<Integer, List<Integer>> additionalProximityChars) { + final HashMap<Integer, Key> keyCodeMap = new HashMap<Integer, Key>(); + for (final Key key : keys) { + keyCodeMap.put(key.mCode, key); + } final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE); final int threshold = thresholdBase * thresholdBase; // Round-up so we don't have any pixels outside the grid - final int[] indices = new int[keys.size()]; + final Key[] neighborKeys = new Key[keys.length]; final int gridWidth = mGridWidth * mCellWidth; final int gridHeight = mGridHeight * mCellHeight; for (int x = 0; x < gridWidth; x += mCellWidth) { @@ -186,31 +201,51 @@ public class ProximityInfo { final int centerX = x + mCellWidth / 2; final int centerY = y + mCellHeight / 2; int count = 0; - for (int i = 0; i < keys.size(); i++) { - final Key key = keys.get(i); + for (final Key key : keys) { if (key.isSpacer()) continue; - if (key.squaredDistanceToEdge(centerX, centerY) < threshold) - indices[count++] = i; + if (key.squaredDistanceToEdge(centerX, centerY) < threshold) { + neighborKeys[count++] = key; + } + } + int currentCodesSize = count; + for (int i = 0; i < currentCodesSize; ++i) { + final int c = neighborKeys[i].mCode; + final List<Integer> additionalChars = additionalProximityChars.get(c); + if (additionalChars == null || additionalChars.size() == 0) { + continue; + } + for (int j = 0; j < additionalChars.size(); ++j) { + final int additionalChar = additionalChars.get(j); + boolean contains = false; + for (int k = 0; k < count; ++k) { + if(additionalChar == neighborKeys[k].mCode) { + contains = true; + break; + } + } + if (!contains) { + neighborKeys[count++] = keyCodeMap.get(additionalChar); + } + } } - final int[] cell = new int[count]; - System.arraycopy(indices, 0, cell, 0, count); - mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = cell; + mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = + Arrays.copyOfRange(neighborKeys, 0, count); } } setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys, touchPositionCorrection); } - public int[] getNearestKeys(int x, int y) { + public Key[] getNearestKeys(int x, int y) { if (mGridNeighbors == null) { - return EMPTY_INT_ARRAY; + return EMPTY_KEY_ARRAY; } if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) { - int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth); + int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth); if (index < mGridSize) { return mGridNeighbors[index]; } } - return EMPTY_INT_ARRAY; + return EMPTY_KEY_ARRAY; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 28a53cedc..5712df1fc 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,29 +18,27 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -import com.android.inputmethod.keyboard.KeyboardSwitcher; +public class AlphabetShiftState { + private static final String TAG = AlphabetShiftState.class.getSimpleName(); + private static final boolean DEBUG = false; -public class KeyboardShiftState { - private static final String TAG = KeyboardShiftState.class.getSimpleName(); - private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE; - - private static final int NORMAL = 0; + private static final int UNSHIFTED = 0; private static final int MANUAL_SHIFTED = 1; private static final int MANUAL_SHIFTED_FROM_AUTO = 2; - private static final int AUTO_SHIFTED = 3; + private static final int AUTOMATIC_SHIFTED = 3; private static final int SHIFT_LOCKED = 4; private static final int SHIFT_LOCK_SHIFTED = 5; - private int mState = NORMAL; + private int mState = UNSHIFTED; - public boolean setShifted(boolean newShiftState) { + public void setShifted(boolean newShiftState) { final int oldState = mState; if (newShiftState) { switch (oldState) { - case NORMAL: + case UNSHIFTED: mState = MANUAL_SHIFTED; break; - case AUTO_SHIFTED: + case AUTOMATIC_SHIFTED: mState = MANUAL_SHIFTED_FROM_AUTO; break; case SHIFT_LOCKED: @@ -51,8 +49,8 @@ public class KeyboardShiftState { switch (oldState) { case MANUAL_SHIFTED: case MANUAL_SHIFTED_FROM_AUTO: - case AUTO_SHIFTED: - mState = NORMAL; + case AUTOMATIC_SHIFTED: + mState = UNSHIFTED; break; case SHIFT_LOCK_SHIFTED: mState = SHIFT_LOCKED; @@ -61,42 +59,36 @@ public class KeyboardShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); - return mState != oldState; } public void setShiftLocked(boolean newShiftLockState) { final int oldState = mState; if (newShiftLockState) { switch (oldState) { - case NORMAL: + case UNSHIFTED: case MANUAL_SHIFTED: case MANUAL_SHIFTED_FROM_AUTO: - case AUTO_SHIFTED: + case AUTOMATIC_SHIFTED: mState = SHIFT_LOCKED; break; } } else { - switch (oldState) { - case SHIFT_LOCKED: - case SHIFT_LOCK_SHIFTED: - mState = NORMAL; - break; - } + mState = UNSHIFTED; } if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); } - public void setAutomaticTemporaryUpperCase() { + public void setAutomaticShifted() { final int oldState = mState; - mState = AUTO_SHIFTED; + mState = AUTOMATIC_SHIFTED; if (DEBUG) - Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this); + Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); } public boolean isShiftedOrShiftLocked() { - return mState != NORMAL; + return mState != UNSHIFTED; } public boolean isShiftLocked() { @@ -107,16 +99,16 @@ public class KeyboardShiftState { return mState == SHIFT_LOCK_SHIFTED; } - public boolean isAutomaticTemporaryUpperCase() { - return mState == AUTO_SHIFTED; + public boolean isAutomaticShifted() { + return mState == AUTOMATIC_SHIFTED; } - public boolean isManualTemporaryUpperCase() { + public boolean isManualShifted() { return mState == MANUAL_SHIFTED || mState == MANUAL_SHIFTED_FROM_AUTO || mState == SHIFT_LOCK_SHIFTED; } - public boolean isManualTemporaryUpperCaseFromAuto() { + public boolean isManualShiftedFromAutomaticShifted() { return mState == MANUAL_SHIFTED_FROM_AUTO; } @@ -127,13 +119,13 @@ public class KeyboardShiftState { private static String toString(int state) { switch (state) { - case NORMAL: return "NORMAL"; + case UNSHIFTED: return "UNSHIFTED"; case MANUAL_SHIFTED: return "MANUAL_SHIFTED"; case MANUAL_SHIFTED_FROM_AUTO: return "MANUAL_SHIFTED_FROM_AUTO"; - case AUTO_SHIFTED: return "AUTO_SHIFTED"; + case AUTOMATIC_SHIFTED: return "AUTOMATIC_SHIFTED"; case SHIFT_LOCKED: return "SHIFT_LOCKED"; case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED"; - default: return "UKNOWN"; + default: return "UNKNOWN"; } } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java new file mode 100644 index 000000000..0aba813b2 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.res.Resources; +import android.text.TextUtils; + +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * String parser of moreKeys attribute of Key. + * The string is comma separated texts each of which represents one "more key". + * - String resource can be embedded into specification @string/name. This is done before parsing + * comma. + * Each "more key" specification is one of the following: + * - A single letter (Letter) + * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText). + * - Icon followed by keyOutputText or code (@icon/icon_name|@integer/key_code) + * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' character. + * Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well. + * See {@link KeyboardIconsSet} about icon_name. + */ +public class KeySpecParser { + private static final boolean DEBUG = LatinImeLogger.sDBG; + + private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; + + // Constants for parsing. + private static int COMMA = ','; + private static final char ESCAPE_CHAR = '\\'; + private static final char PREFIX_AT = '@'; + private static final char SUFFIX_SLASH = '/'; + private static final String PREFIX_STRING = PREFIX_AT + "string" + SUFFIX_SLASH; + private static final char LABEL_END = '|'; + private static final String PREFIX_ICON = PREFIX_AT + "icon" + SUFFIX_SLASH; + private static final String PREFIX_CODE = PREFIX_AT + "integer" + SUFFIX_SLASH; + private static final String ADDITIONAL_MORE_KEY_MARKER = "%"; + + private KeySpecParser() { + // Intentional empty constructor for utility class. + } + + private static boolean hasIcon(String moreKeySpec) { + if (moreKeySpec.startsWith(PREFIX_ICON)) { + final int end = indexOfLabelEnd(moreKeySpec, 0); + if (end > 0) { + return true; + } + throw new KeySpecParserError("outputText or code not specified: " + moreKeySpec); + } + return false; + } + + private static boolean hasCode(String moreKeySpec) { + final int end = indexOfLabelEnd(moreKeySpec, 0); + if (end > 0 && end + 1 < moreKeySpec.length() + && moreKeySpec.substring(end + 1).startsWith(PREFIX_CODE)) { + return true; + } + return false; + } + + private static String parseEscape(String text) { + if (text.indexOf(ESCAPE_CHAR) < 0) { + return text; + } + final int length = text.length(); + final StringBuilder sb = new StringBuilder(); + for (int pos = 0; pos < length; pos++) { + final char c = text.charAt(pos); + if (c == ESCAPE_CHAR && pos + 1 < length) { + // Skip escape char + pos++; + sb.append(text.charAt(pos)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + private static int indexOfLabelEnd(String moreKeySpec, int start) { + if (moreKeySpec.indexOf(ESCAPE_CHAR, start) < 0) { + final int end = moreKeySpec.indexOf(LABEL_END, start); + if (end == 0) { + throw new KeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec); + } + return end; + } + final int length = moreKeySpec.length(); + for (int pos = start; pos < length; pos++) { + final char c = moreKeySpec.charAt(pos); + if (c == ESCAPE_CHAR && pos + 1 < length) { + // Skip escape char + pos++; + } else if (c == LABEL_END) { + return pos; + } + } + return -1; + } + + public static String getLabel(String moreKeySpec) { + if (hasIcon(moreKeySpec)) { + return null; + } + final int end = indexOfLabelEnd(moreKeySpec, 0); + final String label = (end > 0) ? parseEscape(moreKeySpec.substring(0, end)) + : parseEscape(moreKeySpec); + if (TextUtils.isEmpty(label)) { + throw new KeySpecParserError("Empty label: " + moreKeySpec); + } + return label; + } + + private static String getOutputTextInternal(String moreKeySpec) { + final int end = indexOfLabelEnd(moreKeySpec, 0); + if (end <= 0) { + return null; + } + if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) { + throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); + } + return parseEscape(moreKeySpec.substring(end + /* LABEL_END */1)); + } + + public static String getOutputText(String moreKeySpec) { + if (hasCode(moreKeySpec)) { + return null; + } + final String outputText = getOutputTextInternal(moreKeySpec); + if (outputText != null) { + if (StringUtils.codePointCount(outputText) == 1) { + // If output text is one code point, it should be treated as a code. + // See {@link #getCode(Resources, String)}. + return null; + } + if (!TextUtils.isEmpty(outputText)) { + return outputText; + } + throw new KeySpecParserError("Empty outputText: " + moreKeySpec); + } + final String label = getLabel(moreKeySpec); + if (label == null) { + throw new KeySpecParserError("Empty label: " + moreKeySpec); + } + // Code is automatically generated for one letter label. See {@link getCode()}. + return (StringUtils.codePointCount(label) == 1) ? null : label; + } + + public static int getCode(Resources res, String moreKeySpec) { + if (hasCode(moreKeySpec)) { + final int end = indexOfLabelEnd(moreKeySpec, 0); + if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) { + throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); + } + final int resId = getResourceId(res, + moreKeySpec.substring(end + /* LABEL_END */1 + /* PREFIX_AT */1), + R.string.english_ime_name); + final int code = res.getInteger(resId); + return code; + } + final String outputText = getOutputTextInternal(moreKeySpec); + if (outputText != null) { + // If output text is one code point, it should be treated as a code. + // See {@link #getOutputText(String)}. + if (StringUtils.codePointCount(outputText) == 1) { + return outputText.codePointAt(0); + } + return Keyboard.CODE_OUTPUT_TEXT; + } + final String label = getLabel(moreKeySpec); + // Code is automatically generated for one letter label. + if (StringUtils.codePointCount(label) == 1) { + return label.codePointAt(0); + } + return Keyboard.CODE_OUTPUT_TEXT; + } + + public static int getIconId(String moreKeySpec) { + if (hasIcon(moreKeySpec)) { + final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length()); + final String name = moreKeySpec.substring(PREFIX_ICON.length(), end); + return KeyboardIconsSet.getIconId(name); + } + return KeyboardIconsSet.ICON_UNDEFINED; + } + + private static <T> ArrayList<T> arrayAsList(T[] array, int start, int end) { + if (array == null) { + throw new NullPointerException(); + } + if (start < 0 || start > end || end > array.length) { + throw new IllegalArgumentException(); + } + + final ArrayList<T> list = new ArrayList<T>(end - start); + for (int i = start; i < end; i++) { + list.add(array[i]); + } + return list; + } + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static String[] filterOutEmptyString(String[] array) { + if (array == null) { + return EMPTY_STRING_ARRAY; + } + ArrayList<String> out = null; + for (int i = 0; i < array.length; i++) { + final String entry = array[i]; + if (TextUtils.isEmpty(entry)) { + if (out == null) { + out = arrayAsList(array, 0, i); + } + } else if (out != null) { + out.add(entry); + } + } + if (out == null) { + return array; + } else { + return out.toArray(new String[out.size()]); + } + } + + public static String[] insertAddtionalMoreKeys(String[] moreKeySpecs, + String[] additionalMoreKeySpecs) { + final String[] moreKeys = filterOutEmptyString(moreKeySpecs); + final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs); + final int moreKeysCount = moreKeys.length; + final int additionalCount = additionalMoreKeys.length; + ArrayList<String> out = null; + int additionalIndex = 0; + for (int moreKeyIndex = 0; moreKeyIndex < moreKeysCount; moreKeyIndex++) { + final String moreKeySpec = moreKeys[moreKeyIndex]; + if (moreKeySpec.equals(ADDITIONAL_MORE_KEY_MARKER)) { + if (additionalIndex < additionalCount) { + // Replace '%' marker with additional more key specification. + final String additionalMoreKey = additionalMoreKeys[additionalIndex]; + if (out != null) { + out.add(additionalMoreKey); + } else { + moreKeys[moreKeyIndex] = additionalMoreKey; + } + additionalIndex++; + } else { + // Filter out excessive '%' marker. + if (out == null) { + out = arrayAsList(moreKeys, 0, moreKeyIndex); + } + } + } else { + if (out != null) { + out.add(moreKeySpec); + } + } + } + if (additionalCount > 0 && additionalIndex == 0) { + // No '%' marker is found in more keys. + // Insert all additional more keys to the head of more keys. + if (DEBUG && out != null) { + throw new RuntimeException("Internal logic error:" + + " moreKeys=" + Arrays.toString(moreKeys) + + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); + } + out = arrayAsList(additionalMoreKeys, additionalIndex, additionalCount); + for (int i = 0; i < moreKeysCount; i++) { + out.add(moreKeys[i]); + } + } else if (additionalIndex < additionalCount) { + // The number of '%' markers are less than additional more keys. + // Append remained additional more keys to the tail of more keys. + if (DEBUG && out != null) { + throw new RuntimeException("Internal logic error:" + + " moreKeys=" + Arrays.toString(moreKeys) + + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys)); + } + out = arrayAsList(moreKeys, 0, moreKeysCount); + for (int i = additionalIndex; i < additionalCount; i++) { + out.add(additionalMoreKeys[additionalIndex]); + } + } + if (out == null && moreKeysCount > 0) { + return moreKeys; + } else if (out != null && out.size() > 0) { + return out.toArray(new String[out.size()]); + } else { + return null; + } + } + + @SuppressWarnings("serial") + public static class KeySpecParserError extends RuntimeException { + public KeySpecParserError(String message) { + super(message); + } + } + + private static int getResourceId(Resources res, String name, int packageNameResId) { + String packageName = res.getResourcePackageName(packageNameResId); + int resId = res.getIdentifier(name, null, packageName); + if (resId == 0) { + throw new RuntimeException("Unknown resource: " + name); + } + return resId; + } + + private static String resolveStringResource(String rawText, Resources res, + int packageNameResId) { + int level = 0; + String text = rawText; + StringBuilder sb; + do { + level++; + if (level >= MAX_STRING_REFERENCE_INDIRECTION) { + throw new RuntimeException("too many @string/resource indirection: " + text); + } + + final int size = text.length(); + if (size < PREFIX_STRING.length()) { + return text; + } + + sb = null; + for (int pos = 0; pos < size; pos++) { + final char c = text.charAt(pos); + if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) { + if (sb == null) { + sb = new StringBuilder(text.substring(0, pos)); + } + final int end = searchResourceNameEnd(text, pos + PREFIX_STRING.length()); + final String resName = text.substring(pos + 1, end); + final int resId = getResourceId(res, resName, packageNameResId); + sb.append(res.getString(resId)); + pos = end - 1; + } else if (c == ESCAPE_CHAR) { + if (sb != null) { + // Append both escape character and escaped character. + sb.append(text.substring(pos, Math.min(pos + 2, size))); + } + pos++; + } else if (sb != null) { + sb.append(c); + } + } + + if (sb != null) { + text = sb.toString(); + } + } while (sb != null); + + return text; + } + + private static int searchResourceNameEnd(String text, int start) { + final int size = text.length(); + for (int pos = start; pos < size; pos++) { + final char c = text.charAt(pos); + // String resource name should be consisted of [a-z_0-9]. + if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) { + continue; + } + return pos; + } + return size; + } + + public static String[] parseCsvString(String rawText, Resources res, int packageNameResId) { + final String text = resolveStringResource(rawText, res, packageNameResId); + final int size = text.length(); + if (size == 0) { + return null; + } + if (StringUtils.codePointCount(text) == 1) { + return text.codePointAt(0) == COMMA ? null : new String[] { text }; + } + + ArrayList<String> list = null; + int start = 0; + for (int pos = 0; pos < size; pos++) { + final char c = text.charAt(pos); + if (c == COMMA) { + // Skip empty entry. + if (pos - start > 0) { + if (list == null) { + list = new ArrayList<String>(); + } + list.add(text.substring(start, pos)); + } + // Skip comma + start = pos + 1; + } else if (c == ESCAPE_CHAR) { + // Skip escape character and escaped character. + pos++; + } + } + final String remain = (size - start > 0) ? text.substring(start) : null; + if (list == null) { + return remain != null ? new String[] { remain } : null; + } else { + if (remain != null) { + list.add(remain); + } + return list.toArray(new String[list.size()]); + } + } + + public static int getIntValue(String[] moreKeys, String key, int defaultValue) { + if (moreKeys == null) { + return defaultValue; + } + boolean foundValue = false; + int value = defaultValue; + for (int i = 0; i < moreKeys.length; i++) { + final String moreKeySpec = moreKeys[i]; + if (moreKeySpec == null || !moreKeySpec.startsWith(key)) { + continue; + } + moreKeys[i] = null; + try { + if (!foundValue) { + value = Integer.parseInt(moreKeySpec.substring(key.length())); + } + } catch (NumberFormatException e) { + throw new RuntimeException( + "integer should follow after " + key + ": " + moreKeySpec); + } + } + return value; + } + + public static boolean getBooleanValue(String[] moreKeys, String key) { + if (moreKeys == null) { + return false; + } + boolean value = false; + for (int i = 0; i < moreKeys.length; i++) { + final String moreKeySpec = moreKeys[i]; + if (moreKeySpec == null || !moreKeySpec.equals(key)) { + continue; + } + moreKeys[i] = null; + value = true; + } + return value; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java index b385b7a04..9e5c227eb 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java @@ -19,16 +19,17 @@ package com.android.inputmethod.keyboard.internal; import android.content.res.TypedArray; import android.util.Log; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder.ParseException; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; -import java.util.ArrayList; import java.util.HashMap; public class KeyStyles { - private static final String TAG = "KeyStyles"; + private static final String TAG = KeyStyles.class.getSimpleName(); private static final boolean DEBUG = false; private final HashMap<String, DeclaredKeyStyle> mStyles = @@ -36,26 +37,21 @@ public class KeyStyles { private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle(); public interface KeyStyle { - public CharSequence[] getTextArray(TypedArray a, int index); - public CharSequence getText(TypedArray a, int index); + public String[] getStringArray(TypedArray a, int index); + public String getString(TypedArray a, int index); public int getInt(TypedArray a, int index, int defaultValue); - public int getFlag(TypedArray a, int index, int defaultValue); - public boolean getBoolean(TypedArray a, int index, boolean defaultValue); + public int getFlag(TypedArray a, int index); } - /* package */ static class EmptyKeyStyle implements KeyStyle { - private EmptyKeyStyle() { - // Nothing to do. - } - + static class EmptyKeyStyle implements KeyStyle { @Override - public CharSequence[] getTextArray(TypedArray a, int index) { - return parseTextArray(a, index); + public String[] getStringArray(TypedArray a, int index) { + return KeyStyles.parseStringArray(a, index); } @Override - public CharSequence getText(TypedArray a, int index) { - return a.getText(index); + public String getString(TypedArray a, int index) { + return a.getString(index); } @Override @@ -64,170 +60,127 @@ public class KeyStyles { } @Override - public int getFlag(TypedArray a, int index, int defaultValue) { - return a.getInt(index, defaultValue); - } - - @Override - public boolean getBoolean(TypedArray a, int index, boolean defaultValue) { - return a.getBoolean(index, defaultValue); - } - - protected static CharSequence[] parseTextArray(TypedArray a, int index) { - if (!a.hasValue(index)) - return null; - final CharSequence text = a.getText(index); - return parseCsvText(text); - } - - /* package */ static CharSequence[] parseCsvText(CharSequence text) { - final int size = text.length(); - if (size == 0) return null; - if (size == 1) return new CharSequence[] { text }; - final StringBuilder sb = new StringBuilder(); - ArrayList<CharSequence> list = null; - int start = 0; - for (int pos = 0; pos < size; pos++) { - final char c = text.charAt(pos); - if (c == ',') { - if (list == null) list = new ArrayList<CharSequence>(); - if (sb.length() == 0) { - list.add(text.subSequence(start, pos)); - } else { - list.add(sb.toString()); - sb.setLength(0); - } - start = pos + 1; - continue; - } else if (c == '\\') { - if (start == pos) { - // Skip escape character at the beginning of the value. - start++; - pos++; - } else { - if (start < pos && sb.length() == 0) - sb.append(text.subSequence(start, pos)); - pos++; - if (pos < size) - sb.append(text.charAt(pos)); - } - } else if (sb.length() > 0) { - sb.append(c); - } - } - if (list == null) { - return new CharSequence[] { sb.length() > 0 ? sb : text.subSequence(start, size) }; - } else { - list.add(sb.length() > 0 ? sb : text.subSequence(start, size)); - return list.toArray(new CharSequence[list.size()]); - } + public int getFlag(TypedArray a, int index) { + return a.getInt(index, 0); } } - private static class DeclaredKeyStyle extends EmptyKeyStyle { - private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>(); + static class DeclaredKeyStyle implements KeyStyle { + private final HashMap<Integer, Object> mStyleAttributes = new HashMap<Integer, Object>(); @Override - public CharSequence[] getTextArray(TypedArray a, int index) { - return a.hasValue(index) - ? super.getTextArray(a, index) : (CharSequence[])mAttributes.get(index); + public String[] getStringArray(TypedArray a, int index) { + if (a.hasValue(index)) { + return parseStringArray(a, index); + } + return (String[])mStyleAttributes.get(index); } @Override - public CharSequence getText(TypedArray a, int index) { - return a.hasValue(index) - ? super.getText(a, index) : (CharSequence)mAttributes.get(index); + public String getString(TypedArray a, int index) { + if (a.hasValue(index)) { + return a.getString(index); + } + return (String)mStyleAttributes.get(index); } @Override public int getInt(TypedArray a, int index, int defaultValue) { - final Integer value = (Integer)mAttributes.get(index); - return super.getInt(a, index, (value != null) ? value : defaultValue); - } - - @Override - public int getFlag(TypedArray a, int index, int defaultValue) { - final Integer value = (Integer)mAttributes.get(index); - return super.getFlag(a, index, defaultValue) | (value != null ? value : 0); + if (a.hasValue(index)) { + return a.getInt(index, defaultValue); + } + final Integer styleValue = (Integer)mStyleAttributes.get(index); + return styleValue != null ? styleValue : defaultValue; } @Override - public boolean getBoolean(TypedArray a, int index, boolean defaultValue) { - final Boolean value = (Boolean)mAttributes.get(index); - return super.getBoolean(a, index, (value != null) ? value : defaultValue); - } - - private DeclaredKeyStyle() { - super(); + public int getFlag(TypedArray a, int index) { + final int value = a.getInt(index, 0); + final Integer styleValue = (Integer)mStyleAttributes.get(index); + return (styleValue != null ? styleValue : 0) | value; } - private void parseKeyStyleAttributes(TypedArray keyAttr) { + void readKeyAttributes(TypedArray keyAttr) { // TODO: Currently not all Key attributes can be declared as style. readInt(keyAttr, R.styleable.Keyboard_Key_code); - readText(keyAttr, R.styleable.Keyboard_Key_keyLabel); - readText(keyAttr, R.styleable.Keyboard_Key_keyOutputText); - readText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); - readTextArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); - readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelOption); + readInt(keyAttr, R.styleable.Keyboard_Key_altCode); + readString(keyAttr, R.styleable.Keyboard_Key_keyLabel); + readString(keyAttr, R.styleable.Keyboard_Key_keyOutputText); + readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); + readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); + readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); + readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags); readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon); + readInt(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled); readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview); - readInt(keyAttr, R.styleable.Keyboard_Key_keyIconShifted); readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn); readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType); - readBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable); - readBoolean(keyAttr, R.styleable.Keyboard_Key_enabled); + readFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); } - private void readText(TypedArray a, int index) { - if (a.hasValue(index)) - mAttributes.put(index, a.getText(index)); + private void readString(TypedArray a, int index) { + if (a.hasValue(index)) { + mStyleAttributes.put(index, a.getString(index)); + } } private void readInt(TypedArray a, int index) { - if (a.hasValue(index)) - mAttributes.put(index, a.getInt(index, 0)); + if (a.hasValue(index)) { + mStyleAttributes.put(index, a.getInt(index, 0)); + } } private void readFlag(TypedArray a, int index) { - final Integer value = (Integer)mAttributes.get(index); - if (a.hasValue(index)) - mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0)); + final Integer value = (Integer)mStyleAttributes.get(index); + if (a.hasValue(index)) { + mStyleAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0)); + } } - private void readBoolean(TypedArray a, int index) { - if (a.hasValue(index)) - mAttributes.put(index, a.getBoolean(index, false)); + private void readStringArray(TypedArray a, int index) { + final String[] value = parseStringArray(a, index); + if (value != null) { + mStyleAttributes.put(index, value); + } } - private void readTextArray(TypedArray a, int index) { - final CharSequence[] value = parseTextArray(a, index); - if (value != null) - mAttributes.put(index, value); + void addParentStyleAttributes(DeclaredKeyStyle parentStyle) { + mStyleAttributes.putAll(parentStyle.mStyleAttributes); } + } - private void addParent(DeclaredKeyStyle parentStyle) { - mAttributes.putAll(parentStyle.mAttributes); + static String[] parseStringArray(TypedArray a, int index) { + if (a.hasValue(index)) { + return KeySpecParser.parseCsvString( + a.getString(index), a.getResources(), R.string.english_ime_name); } + return null; } public void parseKeyStyleAttributes(TypedArray keyStyleAttr, TypedArray keyAttrs, - XmlPullParser parser) { + XmlPullParser parser) throws XmlPullParserException { final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName); - if (DEBUG) Log.d(TAG, String.format("<%s styleName=%s />", - KeyboardBuilder.TAG_KEY_STYLE, styleName)); - if (mStyles.containsKey(styleName)) - throw new ParseException("duplicate key style declared: " + styleName, parser); + if (DEBUG) { + Log.d(TAG, String.format("<%s styleName=%s />", + Keyboard.Builder.TAG_KEY_STYLE, styleName)); + if (mStyles.containsKey(styleName)) { + Log.d(TAG, "key-style " + styleName + " is overridden at " + + parser.getPositionDescription()); + } + } final DeclaredKeyStyle style = new DeclaredKeyStyle(); if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) { final String parentStyle = keyStyleAttr.getString( R.styleable.Keyboard_KeyStyle_parentStyle); final DeclaredKeyStyle parent = mStyles.get(parentStyle); - if (parent == null) - throw new ParseException("Unknown parentStyle " + parentStyle, parser); - style.addParent(parent); + if (parent == null) { + throw new XmlParseUtils.ParseException( + "Unknown parentStyle " + parentStyle, parser); + } + style.addParentStyleAttributes(parent); } - style.parseKeyStyleAttributes(keyAttrs); + style.readKeyAttributes(keyAttrs); mStyles.put(styleName, style); } @@ -235,7 +188,7 @@ public class KeyStyles { return mStyles.get(styleName); } - public KeyStyle getEmptyKeyStyle() { + public static KeyStyle getEmptyKeyStyle() { return EMPTY_KEY_STYLE; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java deleted file mode 100644 index de64639b0..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ /dev/null @@ -1,893 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.util.Xml; -import android.view.InflateException; - -import com.android.inputmethod.compat.EditorInfoCompatUtils; -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.Arrays; - -/** - * Keyboard Building helper. - * - * This class parses Keyboard XML file and eventually build a Keyboard. - * The Keyboard XML file looks like: - * <pre> - * >!-- xml/keyboard.xml --< - * >Keyboard keyboard_attributes*< - * >!-- Keyboard Content --< - * >Row row_attributes*< - * >!-- Row Content --< - * >Key key_attributes* /< - * >Spacer horizontalGap="0.2in" /< - * >include keyboardLayout="@xml/other_keys"< - * ... - * >/Row< - * >include keyboardLayout="@xml/other_rows"< - * ... - * >/Keyboard< - * </pre> - * The XML file which is included in other file must have >merge< as root element, such as: - * <pre> - * >!-- xml/other_keys.xml --< - * >merge< - * >Key key_attributes* /< - * ... - * >/merge< - * </pre> - * and - * <pre> - * >!-- xml/other_rows.xml --< - * >merge< - * >Row row_attributes*< - * >Key key_attributes* /< - * >/Row< - * ... - * >/merge< - * </pre> - * You can also use switch-case-default tags to select Rows and Keys. - * <pre> - * >switch< - * >case case_attribute*< - * >!-- Any valid tags at switch position --< - * >/case< - * ... - * >default< - * >!-- Any valid tags at switch position --< - * >/default< - * >/switch< - * </pre> - * You can declare Key style and specify styles within Key tags. - * <pre> - * >switch< - * >case mode="email"< - * >key-style styleName="f1-key" parentStyle="modifier-key" - * keyLabel=".com" - * /< - * >/case< - * >case mode="url"< - * >key-style styleName="f1-key" parentStyle="modifier-key" - * keyLabel="http://" - * /< - * >/case< - * >/switch< - * ... - * >Key keyStyle="shift-key" ... /< - * </pre> - */ - -public class KeyboardBuilder<KP extends KeyboardParams> { - private static final String TAG = KeyboardBuilder.class.getSimpleName(); - private static final boolean DEBUG = false; - - // Keyboard XML Tags - private static final String TAG_KEYBOARD = "Keyboard"; - private static final String TAG_ROW = "Row"; - private static final String TAG_KEY = "Key"; - private static final String TAG_SPACER = "Spacer"; - private static final String TAG_INCLUDE = "include"; - private static final String TAG_MERGE = "merge"; - private static final String TAG_SWITCH = "switch"; - private static final String TAG_CASE = "case"; - private static final String TAG_DEFAULT = "default"; - public static final String TAG_KEY_STYLE = "key-style"; - - private static final int DEFAULT_KEYBOARD_COLUMNS = 10; - private static final int DEFAULT_KEYBOARD_ROWS = 4; - - protected final KP mParams; - protected final Context mContext; - protected final Resources mResources; - private final DisplayMetrics mDisplayMetrics; - - private int mCurrentY = 0; - private Row mCurrentRow = null; - private boolean mLeftEdge; - private boolean mTopEdge; - private Key mRightEdgeKey = null; - private final KeyStyles mKeyStyles = new KeyStyles(); - - /** - * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. - * Some of the key size defaults can be overridden per row from what the {@link Keyboard} - * defines. - */ - public static class Row { - // keyWidth enum constants - private static final int KEYWIDTH_NOT_ENUM = 0; - private static final int KEYWIDTH_FILL_RIGHT = -1; - private static final int KEYWIDTH_FILL_BOTH = -2; - - private final KeyboardParams mParams; - /** Default width of a key in this row. */ - public final float mDefaultKeyWidth; - /** Default height of a key in this row. */ - public final int mRowHeight; - - private final int mCurrentY; - // Will be updated by {@link Key}'s constructor. - private float mCurrentX; - - public Row(Resources res, KeyboardParams params, XmlPullParser parser, int y) { - mParams = params; - TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard); - mRowHeight = (int)KeyboardBuilder.getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_rowHeight, params.mBaseHeight, params.mDefaultRowHeight); - keyboardAttr.recycle(); - TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_Key); - mDefaultKeyWidth = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth, params.mDefaultKeyWidth); - keyAttr.recycle(); - - mCurrentY = y; - mCurrentX = 0.0f; - } - - public void setXPos(float keyXPos) { - mCurrentX = keyXPos; - } - - public void advanceXPos(float width) { - mCurrentX += width; - } - - public int getKeyY() { - return mCurrentY; - } - - public float getKeyX(TypedArray keyAttr) { - final int widthType = KeyboardBuilder.getEnumValue(keyAttr, - R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM); - if (widthType == KEYWIDTH_FILL_BOTH) { - // If keyWidth is fillBoth, the key width should start right after the nearest key - // on the left hand side. - return mCurrentX; - } - - final int keyboardRightEdge = mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding; - if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyXPos)) { - final float keyXPos = KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyXPos, mParams.mBaseWidth, 0); - if (keyXPos < 0) { - // If keyXPos is negative, the actual x-coordinate will be - // keyboardWidth + keyXPos. - // keyXPos shouldn't be less than mCurrentX because drawable area for this key - // starts at mCurrentX. Or, this key will overlaps the adjacent key on its left - // hand side. - return Math.max(keyXPos + keyboardRightEdge, mCurrentX); - } else { - return keyXPos + mParams.mHorizontalEdgesPadding; - } - } - return mCurrentX; - } - - public float getKeyWidth(TypedArray keyAttr, float keyXPos) { - final int widthType = KeyboardBuilder.getEnumValue(keyAttr, - R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM); - switch (widthType) { - case KEYWIDTH_FILL_RIGHT: - case KEYWIDTH_FILL_BOTH: - final int keyboardRightEdge = - mParams.mOccupiedWidth - mParams.mHorizontalEdgesPadding; - // If keyWidth is fillRight, the actual key width will be determined to fill out the - // area up to the right edge of the keyboard. - // If keyWidth is fillBoth, the actual key width will be determined to fill out the - // area between the nearest key on the left hand side and the right edge of the - // keyboard. - return keyboardRightEdge - keyXPos; - default: // KEYWIDTH_NOT_ENUM - return KeyboardBuilder.getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyWidth, mParams.mBaseWidth, mDefaultKeyWidth); - } - } - } - - public KeyboardBuilder(Context context, KP params) { - mContext = context; - final Resources res = context.getResources(); - mResources = res; - mDisplayMetrics = res.getDisplayMetrics(); - - mParams = params; - - setTouchPositionCorrectionData(context, params); - - params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); - params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); - } - - private static void setTouchPositionCorrectionData(Context context, KeyboardParams params) { - final TypedArray a = context.obtainStyledAttributes( - null, R.styleable.Keyboard, R.attr.keyboardStyle, 0); - params.mThemeId = a.getInt(R.styleable.Keyboard_themeId, 0); - final int resourceId = a.getResourceId(R.styleable.Keyboard_touchPositionCorrectionData, 0); - a.recycle(); - if (resourceId == 0) { - if (LatinImeLogger.sDBG) - throw new RuntimeException("touchPositionCorrectionData is not defined"); - return; - } - - final String[] data = context.getResources().getStringArray(resourceId); - params.mTouchPositionCorrection.load(data); - } - - public KeyboardBuilder<KP> load(KeyboardId id) { - mParams.mId = id; - final XmlResourceParser parser = mResources.getXml(id.getXmlId()); - try { - parseKeyboard(parser); - } catch (XmlPullParserException e) { - Log.w(TAG, "keyboard XML parse error: " + e); - throw new IllegalArgumentException(e); - } catch (IOException e) { - Log.w(TAG, "keyboard XML parse error: " + e); - throw new RuntimeException(e); - } finally { - parser.close(); - } - return this; - } - - public void setTouchPositionCorrectionEnabled(boolean enabled) { - mParams.mTouchPositionCorrection.setEnabled(enabled); - } - - public Keyboard build() { - return new Keyboard(mParams); - } - - private void parseKeyboard(XmlResourceParser parser) - throws XmlPullParserException, IOException { - if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mParams.mId)); - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_KEYBOARD.equals(tag)) { - parseKeyboardAttributes(parser); - startKeyboard(); - parseKeyboardContent(parser, false); - break; - } else { - throw new IllegalStartTag(parser, TAG_KEYBOARD); - } - } - } - } - - public static String parseKeyboardLocale( - Context context, int resId) throws XmlPullParserException, IOException { - final Resources res = context.getResources(); - final XmlPullParser parser = res.getXml(resId); - if (parser == null) return ""; - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_KEYBOARD.equals(tag)) { - final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard); - final String locale = keyboardAttr.getString( - R.styleable.Keyboard_keyboardLocale); - keyboardAttr.recycle(); - return locale; - } else { - throw new IllegalStartTag(parser, TAG_KEYBOARD); - } - } - } - return ""; - } - - private void parseKeyboardAttributes(XmlPullParser parser) { - final int displayWidth = mDisplayMetrics.widthPixels; - final TypedArray keyboardAttr = mContext.obtainStyledAttributes( - Xml.asAttributeSet(parser), R.styleable.Keyboard, R.attr.keyboardStyle, - R.style.Keyboard); - final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_Key); - try { - final int displayHeight = mDisplayMetrics.heightPixels; - final int keyboardHeight = (int)keyboardAttr.getDimension( - R.styleable.Keyboard_keyboardHeight, displayHeight / 2); - final int maxKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2); - int minKeyboardHeight = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_minKeyboardHeight, displayHeight, displayHeight / 2); - if (minKeyboardHeight < 0) { - // Specified fraction was negative, so it should be calculated against display - // width. - minKeyboardHeight = -(int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_minKeyboardHeight, displayWidth, displayWidth / 2); - } - final KeyboardParams params = mParams; - // Keyboard height will not exceed maxKeyboardHeight and will not be less than - // minKeyboardHeight. - params.mOccupiedHeight = Math.max( - Math.min(keyboardHeight, maxKeyboardHeight), minKeyboardHeight); - params.mOccupiedWidth = params.mId.mWidth; - params.mTopPadding = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_keyboardTopPadding, params.mOccupiedHeight, 0); - params.mBottomPadding = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_keyboardBottomPadding, params.mOccupiedHeight, 0); - params.mHorizontalEdgesPadding = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_keyboardHorizontalEdgesPadding, mParams.mOccupiedWidth, 0); - - params.mBaseWidth = params.mOccupiedWidth - params.mHorizontalEdgesPadding * 2 - - params.mHorizontalCenterPadding; - params.mDefaultKeyWidth = (int)getDimensionOrFraction(keyAttr, - R.styleable.Keyboard_Key_keyWidth, params.mBaseWidth, - params.mBaseWidth / DEFAULT_KEYBOARD_COLUMNS); - params.mHorizontalGap = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_horizontalGap, params.mBaseWidth, 0); - params.mVerticalGap = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_verticalGap, params.mOccupiedHeight, 0); - params.mBaseHeight = params.mOccupiedHeight - params.mTopPadding - - params.mBottomPadding + params.mVerticalGap; - params.mDefaultRowHeight = (int)getDimensionOrFraction(keyboardAttr, - R.styleable.Keyboard_rowHeight, params.mBaseHeight, - params.mBaseHeight / DEFAULT_KEYBOARD_ROWS); - - params.mIsRtlKeyboard = keyboardAttr.getBoolean( - R.styleable.Keyboard_isRtlKeyboard, false); - params.mMoreKeysTemplate = keyboardAttr.getResourceId( - R.styleable.Keyboard_moreKeysTemplate, 0); - params.mMaxMiniKeyboardColumn = keyAttr.getInt( - R.styleable.Keyboard_Key_maxMoreKeysColumn, 5); - - params.mIconsSet.loadIcons(keyboardAttr); - } finally { - keyAttr.recycle(); - keyboardAttr.recycle(); - } - } - - private void parseKeyboardContent(XmlPullParser parser, boolean skip) - throws XmlPullParserException, IOException { - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_ROW.equals(tag)) { - Row row = parseRowAttributes(parser); - if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_ROW)); - if (!skip) - startRow(row); - parseRowContent(parser, row, skip); - } else if (TAG_INCLUDE.equals(tag)) { - parseIncludeKeyboardContent(parser, skip); - } else if (TAG_SWITCH.equals(tag)) { - parseSwitchKeyboardContent(parser, skip); - } else if (TAG_KEY_STYLE.equals(tag)) { - parseKeyStyle(parser, skip); - } else { - throw new IllegalStartTag(parser, TAG_ROW); - } - } else if (event == XmlPullParser.END_TAG) { - final String tag = parser.getName(); - if (TAG_KEYBOARD.equals(tag)) { - endKeyboard(); - break; - } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) - || TAG_MERGE.equals(tag)) { - if (DEBUG) Log.d(TAG, String.format("</%s>", tag)); - break; - } else if (TAG_KEY_STYLE.equals(tag)) { - continue; - } else { - throw new IllegalEndTag(parser, TAG_ROW); - } - } - } - } - - private Row parseRowAttributes(XmlPullParser parser) { - final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard); - try { - if (a.hasValue(R.styleable.Keyboard_horizontalGap)) - throw new IllegalAttribute(parser, "horizontalGap"); - if (a.hasValue(R.styleable.Keyboard_verticalGap)) - throw new IllegalAttribute(parser, "verticalGap"); - return new Row(mResources, mParams, parser, mCurrentY); - } finally { - a.recycle(); - } - } - - private void parseRowContent(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_KEY.equals(tag)) { - parseKey(parser, row, skip); - } else if (TAG_SPACER.equals(tag)) { - parseSpacer(parser, row, skip); - } else if (TAG_INCLUDE.equals(tag)) { - parseIncludeRowContent(parser, row, skip); - } else if (TAG_SWITCH.equals(tag)) { - parseSwitchRowContent(parser, row, skip); - } else if (TAG_KEY_STYLE.equals(tag)) { - parseKeyStyle(parser, skip); - } else { - throw new IllegalStartTag(parser, TAG_KEY); - } - } else if (event == XmlPullParser.END_TAG) { - final String tag = parser.getName(); - if (TAG_ROW.equals(tag)) { - if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW)); - if (!skip) - endRow(row); - break; - } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) - || TAG_MERGE.equals(tag)) { - if (DEBUG) Log.d(TAG, String.format("</%s>", tag)); - break; - } else if (TAG_KEY_STYLE.equals(tag)) { - continue; - } else { - throw new IllegalEndTag(parser, TAG_KEY); - } - } - } - } - - private void parseKey(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - if (skip) { - checkEndTag(TAG_KEY, parser); - } else { - final Key key = new Key(mResources, mParams, row, parser, mKeyStyles); - if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />", - TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode, - Arrays.toString(key.mMoreKeys))); - checkEndTag(TAG_KEY, parser); - endKey(key); - } - } - - private void parseSpacer(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - if (skip) { - checkEndTag(TAG_SPACER, parser); - } else { - final Key.Spacer spacer = new Key.Spacer(mResources, mParams, row, parser, mKeyStyles); - if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER)); - checkEndTag(TAG_SPACER, parser); - endKey(spacer); - } - } - - private void parseIncludeKeyboardContent(XmlPullParser parser, boolean skip) - throws XmlPullParserException, IOException { - parseIncludeInternal(parser, null, skip); - } - - private void parseIncludeRowContent(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - parseIncludeInternal(parser, row, skip); - } - - private void parseIncludeInternal(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - if (skip) { - checkEndTag(TAG_INCLUDE, parser); - } else { - final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_Include); - final int keyboardLayout = a.getResourceId( - R.styleable.Keyboard_Include_keyboardLayout, 0); - a.recycle(); - - checkEndTag(TAG_INCLUDE, parser); - if (keyboardLayout == 0) - throw new ParseException("No keyboardLayout attribute in <include/>", parser); - if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />", - TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout))); - final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout); - try { - parseMerge(parserForInclude, row, skip); - } finally { - parserForInclude.close(); - } - } - } - - private void parseMerge(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_MERGE.equals(tag)) { - if (row == null) { - parseKeyboardContent(parser, skip); - } else { - parseRowContent(parser, row, skip); - } - break; - } else { - throw new ParseException( - "Included keyboard layout must have <merge> root element", parser); - } - } - } - } - - private void parseSwitchKeyboardContent(XmlPullParser parser, boolean skip) - throws XmlPullParserException, IOException { - parseSwitchInternal(parser, null, skip); - } - - private void parseSwitchRowContent(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - parseSwitchInternal(parser, row, skip); - } - - private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_SWITCH, mParams.mId)); - boolean selected = false; - int event; - while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { - if (event == XmlPullParser.START_TAG) { - final String tag = parser.getName(); - if (TAG_CASE.equals(tag)) { - selected |= parseCase(parser, row, selected ? true : skip); - } else if (TAG_DEFAULT.equals(tag)) { - selected |= parseDefault(parser, row, selected ? true : skip); - } else { - throw new IllegalStartTag(parser, TAG_KEY); - } - } else if (event == XmlPullParser.END_TAG) { - final String tag = parser.getName(); - if (TAG_SWITCH.equals(tag)) { - if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH)); - break; - } else { - throw new IllegalEndTag(parser, TAG_KEY); - } - } - } - } - - private boolean parseCase(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - final boolean selected = parseCaseCondition(parser); - if (row == null) { - // Processing Rows. - parseKeyboardContent(parser, selected ? skip : true); - } else { - // Processing Keys. - parseRowContent(parser, row, selected ? skip : true); - } - return selected; - } - - private boolean parseCaseCondition(XmlPullParser parser) { - final KeyboardId id = mParams.mId; - if (id == null) - return true; - - final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_Case); - try { - final boolean modeMatched = matchTypedValue(a, - R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode)); - final boolean navigateActionMatched = matchBoolean(a, - R.styleable.Keyboard_Case_navigateAction, id.mNavigateAction); - final boolean passwordInputMatched = matchBoolean(a, - R.styleable.Keyboard_Case_passwordInput, id.mPasswordInput); - final boolean hasSettingsKeyMatched = matchBoolean(a, - R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey); - final boolean f2KeyModeMatched = matchInteger(a, - R.styleable.Keyboard_Case_f2KeyMode, id.mF2KeyMode); - final boolean clobberSettingsKeyMatched = matchBoolean(a, - R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey); - final boolean shortcutKeyEnabledMatched = matchBoolean(a, - R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled); - final boolean hasShortcutKeyMatched = matchBoolean(a, - R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey); - // As noted at {@link KeyboardId} class, we are interested only in enum value masked by - // {@link android.view.inputmethod.EditorInfo#IME_MASK_ACTION} and - // {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching - // this attribute with id.mImeOptions as integer value is enough for our purpose. - final boolean imeActionMatched = matchInteger(a, - R.styleable.Keyboard_Case_imeAction, id.mImeAction); - final boolean localeCodeMatched = matchString(a, - R.styleable.Keyboard_Case_localeCode, id.mLocale.toString()); - final boolean languageCodeMatched = matchString(a, - R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage()); - final boolean countryCodeMatched = matchString(a, - R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry()); - final boolean selected = modeMatched && navigateActionMatched && passwordInputMatched - && hasSettingsKeyMatched && f2KeyModeMatched && clobberSettingsKeyMatched - && shortcutKeyEnabledMatched && hasShortcutKeyMatched && imeActionMatched && - localeCodeMatched && languageCodeMatched && countryCodeMatched; - - if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s%s%s%s%s> %s", TAG_CASE, - textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"), - booleanAttr(a, R.styleable.Keyboard_Case_navigateAction, "navigateAction"), - booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"), - booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"), - textAttr(KeyboardId.f2KeyModeName( - a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), "f2KeyMode"), - booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey, - "clobberSettingsKey"), - booleanAttr( - a, R.styleable.Keyboard_Case_shortcutKeyEnabled, "shortcutKeyEnabled"), - booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"), - textAttr(EditorInfoCompatUtils.imeOptionsName( - a.getInt(R.styleable.Keyboard_Case_imeAction, -1)), "imeAction"), - textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), "localeCode"), - textAttr(a.getString(R.styleable.Keyboard_Case_languageCode), "languageCode"), - textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), "countryCode"), - Boolean.toString(selected))); - - return selected; - } finally { - a.recycle(); - } - } - - private static boolean matchInteger(TypedArray a, int index, int value) { - // If <case> does not have "index" attribute, that means this <case> is wild-card for the - // attribute. - return !a.hasValue(index) || a.getInt(index, 0) == value; - } - - private static boolean matchBoolean(TypedArray a, int index, boolean value) { - // If <case> does not have "index" attribute, that means this <case> is wild-card for the - // attribute. - return !a.hasValue(index) || a.getBoolean(index, false) == value; - } - - private static boolean matchString(TypedArray a, int index, String value) { - // If <case> does not have "index" attribute, that means this <case> is wild-card for the - // attribute. - return !a.hasValue(index) || stringArrayContains(a.getString(index).split("\\|"), value); - } - - private static boolean matchTypedValue(TypedArray a, int index, int intValue, String strValue) { - // If <case> does not have "index" attribute, that means this <case> is wild-card for the - // attribute. - final TypedValue v = a.peekValue(index); - if (v == null) - return true; - - if (isIntegerValue(v)) { - return intValue == a.getInt(index, 0); - } else if (isStringValue(v)) { - return stringArrayContains(a.getString(index).split("\\|"), strValue); - } - return false; - } - - private static boolean stringArrayContains(String[] array, String value) { - for (final String elem : array) { - if (elem.equals(value)) - return true; - } - return false; - } - - private boolean parseDefault(XmlPullParser parser, Row row, boolean skip) - throws XmlPullParserException, IOException { - if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_DEFAULT)); - if (row == null) { - parseKeyboardContent(parser, skip); - } else { - parseRowContent(parser, row, skip); - } - return true; - } - - private void parseKeyStyle(XmlPullParser parser, boolean skip) { - TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_KeyStyle); - TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser), - R.styleable.Keyboard_Key); - try { - if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName)) - throw new ParseException("<" + TAG_KEY_STYLE - + "/> needs styleName attribute", parser); - if (!skip) - mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser); - } finally { - keyStyleAttr.recycle(); - keyAttrs.recycle(); - } - } - - private static void checkEndTag(String tag, XmlPullParser parser) - throws XmlPullParserException, IOException { - if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName())) - return; - throw new NonEmptyTag(tag, parser); - } - - private void startKeyboard() { - mCurrentY += mParams.mTopPadding; - mTopEdge = true; - } - - private void startRow(Row row) { - addEdgeSpace(mParams.mHorizontalEdgesPadding, row); - mCurrentRow = row; - mLeftEdge = true; - mRightEdgeKey = null; - } - - private void endRow(Row row) { - if (mCurrentRow == null) - throw new InflateException("orphant end row tag"); - if (mRightEdgeKey != null) { - mRightEdgeKey.markAsRightEdge(mParams); - mRightEdgeKey = null; - } - addEdgeSpace(mParams.mHorizontalEdgesPadding, row); - mCurrentY += row.mRowHeight; - mCurrentRow = null; - mTopEdge = false; - } - - private void endKey(Key key) { - mParams.onAddKey(key); - if (mLeftEdge) { - key.markAsLeftEdge(mParams); - mLeftEdge = false; - } - if (mTopEdge) { - key.markAsTopEdge(mParams); - } - mRightEdgeKey = key; - } - - private void endKeyboard() { - } - - private void addEdgeSpace(float width, Row row) { - row.advanceXPos(width); - mLeftEdge = false; - mRightEdgeKey = null; - } - - public static float getDimensionOrFraction(TypedArray a, int index, int base, float defValue) { - final TypedValue value = a.peekValue(index); - if (value == null) - return defValue; - if (isFractionValue(value)) { - return a.getFraction(index, base, base, defValue); - } else if (isDimensionValue(value)) { - return a.getDimension(index, defValue); - } - return defValue; - } - - public static int getEnumValue(TypedArray a, int index, int defValue) { - final TypedValue value = a.peekValue(index); - if (value == null) - return defValue; - if (isIntegerValue(value)) { - return a.getInt(index, defValue); - } - return defValue; - } - - private static boolean isFractionValue(TypedValue v) { - return v.type == TypedValue.TYPE_FRACTION; - } - - private static boolean isDimensionValue(TypedValue v) { - return v.type == TypedValue.TYPE_DIMENSION; - } - - private static boolean isIntegerValue(TypedValue v) { - return v.type >= TypedValue.TYPE_FIRST_INT && v.type <= TypedValue.TYPE_LAST_INT; - } - - private static boolean isStringValue(TypedValue v) { - return v.type == TypedValue.TYPE_STRING; - } - - @SuppressWarnings("serial") - public static class ParseException extends InflateException { - public ParseException(String msg, XmlPullParser parser) { - super(msg + " at line " + parser.getLineNumber()); - } - } - - @SuppressWarnings("serial") - private static class IllegalStartTag extends ParseException { - public IllegalStartTag(XmlPullParser parser, String parent) { - super("Illegal start tag " + parser.getName() + " in " + parent, parser); - } - } - - @SuppressWarnings("serial") - private static class IllegalEndTag extends ParseException { - public IllegalEndTag(XmlPullParser parser, String parent) { - super("Illegal end tag " + parser.getName() + " in " + parent, parser); - } - } - - @SuppressWarnings("serial") - private static class IllegalAttribute extends ParseException { - public IllegalAttribute(XmlPullParser parser, String attribute) { - super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser); - } - } - - @SuppressWarnings("serial") - private static class NonEmptyTag extends ParseException { - public NonEmptyTag(String tag, XmlPullParser parser) { - super(tag + " must be empty tag", parser); - } - } - - private static String textAttr(String value, String name) { - return value != null ? String.format(" %s=%s", name, value) : ""; - } - - private static String booleanAttr(TypedArray a, int index, String name) { - return a.hasValue(index) ? String.format(" %s=%s", name, a.getBoolean(index, false)) : ""; - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index faa5f86f2..9b9c86179 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -23,86 +23,92 @@ import android.util.Log; import com.android.inputmethod.latin.R; +import java.util.HashMap; + public class KeyboardIconsSet { private static final String TAG = KeyboardIconsSet.class.getSimpleName(); + // The value should be aligned with the enum value of Key.keyIcon. public static final int ICON_UNDEFINED = 0; + private static final int NUM_ICONS = 14; + + private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1]; - // This should be aligned with Keyboard.keyIcon enum. - private static final int ICON_SHIFT_KEY = 1; - private static final int ICON_DELETE_KEY = 2; - private static final int ICON_SETTINGS_KEY = 3; // This is also represented as "@icon/3" in XML. - private static final int ICON_SPACE_KEY = 4; - private static final int ICON_RETURN_KEY = 5; - private static final int ICON_SEARCH_KEY = 6; - private static final int ICON_TAB_KEY = 7; // This is also represented as "@icon/7" in XML. - private static final int ICON_SHORTCUT_KEY = 8; - private static final int ICON_SHORTCUT_FOR_LABEL = 9; - // This should be aligned with Keyboard.keyIconShifted enum. - private static final int ICON_SHIFTED_SHIFT_KEY = 10; - // This should be aligned with Keyboard.keyIconPreview enum. - private static final int ICON_PREVIEW_TAB_KEY = 11; - - private static final int ICON_LAST = 11; - - private final Drawable mIcons[] = new Drawable[ICON_LAST + 1]; - - private static final int getIconId(final int attrIndex) { - switch (attrIndex) { - case R.styleable.Keyboard_iconShiftKey: - return ICON_SHIFT_KEY; - case R.styleable.Keyboard_iconDeleteKey: - return ICON_DELETE_KEY; - case R.styleable.Keyboard_iconSettingsKey: - return ICON_SETTINGS_KEY; - case R.styleable.Keyboard_iconSpaceKey: - return ICON_SPACE_KEY; - case R.styleable.Keyboard_iconReturnKey: - return ICON_RETURN_KEY; - case R.styleable.Keyboard_iconSearchKey: - return ICON_SEARCH_KEY; - case R.styleable.Keyboard_iconTabKey: - return ICON_TAB_KEY; - case R.styleable.Keyboard_iconShortcutKey: - return ICON_SHORTCUT_KEY; - case R.styleable.Keyboard_iconShortcutForLabel: - return ICON_SHORTCUT_FOR_LABEL; - case R.styleable.Keyboard_iconShiftedShiftKey: - return ICON_SHIFTED_SHIFT_KEY; - case R.styleable.Keyboard_iconPreviewTabKey: - return ICON_PREVIEW_TAB_KEY; - default: - return ICON_UNDEFINED; + private static final HashMap<Integer, Integer> ATTR_ID_TO_ICON_ID + = new HashMap<Integer, Integer>(); + private static final HashMap<String, Integer> NAME_TO_ICON_ID = new HashMap<String, Integer>(); + private static final String[] ICON_NAMES = new String[NUM_ICONS + 1]; + + private static final int ATTR_UNDEFINED = 0; + static { + // The key value should be aligned with the enum value of Key.keyIcon. + addIconIdMap(0, "undefined", ATTR_UNDEFINED); + addIconIdMap(1, "shiftKey", R.styleable.Keyboard_iconShiftKey); + addIconIdMap(2, "deleteKey", R.styleable.Keyboard_iconDeleteKey); + addIconIdMap(3, "settingsKey", R.styleable.Keyboard_iconSettingsKey); + addIconIdMap(4, "spaceKey", R.styleable.Keyboard_iconSpaceKey); + addIconIdMap(5, "returnKey", R.styleable.Keyboard_iconReturnKey); + addIconIdMap(6, "searchKey", R.styleable.Keyboard_iconSearchKey); + addIconIdMap(7, "tabKey", R.styleable.Keyboard_iconTabKey); + addIconIdMap(8, "shortcutKey", R.styleable.Keyboard_iconShortcutKey); + addIconIdMap(9, "shortcutForLabel", R.styleable.Keyboard_iconShortcutForLabel); + addIconIdMap(10, "spaceKeyForNumberLayout", + R.styleable.Keyboard_iconSpaceKeyForNumberLayout); + addIconIdMap(11, "shiftKeyShifted", R.styleable.Keyboard_iconShiftKeyShifted); + addIconIdMap(12, "disabledShortcurKey", R.styleable.Keyboard_iconDisabledShortcutKey); + addIconIdMap(13, "previewTabKey", R.styleable.Keyboard_iconPreviewTabKey); + addIconIdMap(14, "languageSwitchKey", R.styleable.Keyboard_iconLanguageSwitchKey); + } + + private static void addIconIdMap(int iconId, String name, int attrId) { + if (attrId != ATTR_UNDEFINED) { + ATTR_ID_TO_ICON_ID.put(attrId, iconId); } + NAME_TO_ICON_ID.put(name, iconId); + ICON_NAMES[iconId] = name; } public void loadIcons(final TypedArray keyboardAttrs) { - final int count = keyboardAttrs.getIndexCount(); - for (int i = 0; i < count; i++) { - final int attrIndex = keyboardAttrs.getIndex(i); - final int iconId = getIconId(attrIndex); - if (iconId != ICON_UNDEFINED) { - try { - mIcons[iconId] = setDefaultBounds(keyboardAttrs.getDrawable(attrIndex)); - } catch (Resources.NotFoundException e) { - Log.w(TAG, "Drawable resource for icon #" + iconId + " not found"); - } + for (final Integer attrId : ATTR_ID_TO_ICON_ID.keySet()) { + try { + final Drawable icon = keyboardAttrs.getDrawable(attrId); + setDefaultBounds(icon); + final Integer iconId = ATTR_ID_TO_ICON_ID.get(attrId); + mIcons[iconId] = icon; + } catch (Resources.NotFoundException e) { + Log.w(TAG, "Drawable resource for icon #" + + keyboardAttrs.getResources().getResourceEntryName(attrId) + + " not found"); } } } - public Drawable getIcon(final int iconId) { - if (iconId == ICON_UNDEFINED) - return null; - if (iconId < 0 || iconId >= mIcons.length) - throw new IllegalArgumentException("icon id is out of range: " + iconId); - return mIcons[iconId]; + private static boolean isValidIconId(final int iconId) { + return iconId >= 0 && iconId < ICON_NAMES.length; + } + + public static String getIconName(final int iconId) { + return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">"; + } + + public static int getIconId(final String name) { + final Integer iconId = NAME_TO_ICON_ID.get(name); + if (iconId != null) { + return iconId; + } + throw new RuntimeException("unknown icon name: " + name); + } + + public Drawable getIconDrawable(final int iconId) { + if (isValidIconId(iconId)) { + return mIcons[iconId]; + } + throw new RuntimeException("unknown icon id: " + getIconName(iconId)); } - private static Drawable setDefaultBounds(final Drawable icon) { + private static void setDefaultBounds(final Drawable icon) { if (icon != null) { icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); } - return icon; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java deleted file mode 100644 index 64cd37c4b..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2011 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.keyboard.internal; - -import android.graphics.drawable.Drawable; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.LatinImeLogger; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class KeyboardParams { - public KeyboardId mId; - public int mThemeId; - - /** Total height and width of the keyboard, including the paddings and keys */ - public int mOccupiedHeight; - public int mOccupiedWidth; - - /** Base height and width of the keyboard used to calculate rows' or keys' heights and widths */ - public int mBaseHeight; - public int mBaseWidth; - - public int mTopPadding; - public int mBottomPadding; - public int mHorizontalEdgesPadding; - public int mHorizontalCenterPadding; - - public int mDefaultRowHeight; - public int mDefaultKeyWidth; - public int mHorizontalGap; - public int mVerticalGap; - - public boolean mIsRtlKeyboard; - public int mMoreKeysTemplate; - public int mMaxMiniKeyboardColumn; - - public int GRID_WIDTH; - public int GRID_HEIGHT; - - public final List<Key> mKeys = new ArrayList<Key>(); - public final List<Key> mShiftKeys = new ArrayList<Key>(); - public final Set<Key> mShiftLockKeys = new HashSet<Key>(); - public final Map<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>(); - public final Map<Key, Drawable> mUnshiftedIcons = new HashMap<Key, Drawable>(); - public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); - - public int mMostCommonKeyHeight = 0; - public int mMostCommonKeyWidth = 0; - - public final TouchPositionCorrection mTouchPositionCorrection = new TouchPositionCorrection(); - - public static class TouchPositionCorrection { - private static final int TOUCH_POSITION_CORRECTION_RECORD_SIZE = 3; - - public boolean mEnabled; - public float[] mXs; - public float[] mYs; - public float[] mRadii; - - public void load(String[] data) { - final int dataLength = data.length; - if (dataLength % TOUCH_POSITION_CORRECTION_RECORD_SIZE != 0) { - if (LatinImeLogger.sDBG) - throw new RuntimeException( - "the size of touch position correction data is invalid"); - return; - } - - final int length = dataLength / TOUCH_POSITION_CORRECTION_RECORD_SIZE; - mXs = new float[length]; - mYs = new float[length]; - mRadii = new float[length]; - try { - for (int i = 0; i < dataLength; ++i) { - final int type = i % TOUCH_POSITION_CORRECTION_RECORD_SIZE; - final int index = i / TOUCH_POSITION_CORRECTION_RECORD_SIZE; - final float value = Float.parseFloat(data[i]); - if (type == 0) { - mXs[index] = value; - } else if (type == 1) { - mYs[index] = value; - } else { - mRadii[index] = value; - } - } - } catch (NumberFormatException e) { - if (LatinImeLogger.sDBG) { - throw new RuntimeException( - "the number format for touch position correction data is invalid"); - } - mXs = null; - mYs = null; - mRadii = null; - } - } - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - } - - public boolean isValid() { - return mEnabled && mXs != null && mYs != null && mRadii != null - && mXs.length > 0 && mYs.length > 0 && mRadii.length > 0; - } - } - - protected void clearKeys() { - mKeys.clear(); - mShiftKeys.clear(); - mShiftLockKeys.clear(); - mShiftedIcons.clear(); - mUnshiftedIcons.clear(); - clearHistogram(); - } - - public void onAddKey(Key key) { - mKeys.add(key); - updateHistogram(key); - if (key.mCode == Keyboard.CODE_SHIFT) { - mShiftKeys.add(key); - if (key.isSticky()) { - mShiftLockKeys.add(key); - } - } - } - - public void addShiftedIcon(Key key, Drawable icon) { - mUnshiftedIcons.put(key, key.getIcon()); - mShiftedIcons.put(key, icon); - } - - private int mMaxHeightCount = 0; - private int mMaxWidthCount = 0; - private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>(); - private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>(); - - private void clearHistogram() { - mMostCommonKeyHeight = 0; - mMaxHeightCount = 0; - mHeightHistogram.clear(); - - mMaxWidthCount = 0; - mMostCommonKeyWidth = 0; - mWidthHistogram.clear(); - } - - private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) { - final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1; - histogram.put(key, count); - return count; - } - - private void updateHistogram(Key key) { - final Integer height = key.mHeight + key.mVerticalGap; - final int heightCount = updateHistogramCounter(mHeightHistogram, height); - if (heightCount > mMaxHeightCount) { - mMaxHeightCount = heightCount; - mMostCommonKeyHeight = height; - } - - final Integer width = key.mWidth + key.mHorizontalGap; - final int widthCount = updateHistogramCounter(mWidthHistogram, width); - if (widthCount > mMaxWidthCount) { - mMaxWidthCount = widthCount; - mMostCommonKeyWidth = width; - } - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java new file mode 100644 index 000000000..18a3f9794 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -0,0 +1,600 @@ +/* + * Copyright (C) 2011 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.keyboard.internal; + +import android.text.TextUtils; +import android.util.Log; + +import com.android.inputmethod.keyboard.Keyboard; + +/** + * Keyboard state machine. + * + * 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)}. + * + * The actions are {@link SwitchActions}'s methods. + */ +public class KeyboardState { + private static final String TAG = KeyboardState.class.getSimpleName(); + private static final boolean DEBUG_EVENT = false; + private static final boolean DEBUG_ACTION = false; + + public interface SwitchActions { + public void setAlphabetKeyboard(); + public void setAlphabetManualShiftedKeyboard(); + public void setAlphabetAutomaticShiftedKeyboard(); + public void setAlphabetShiftLockedKeyboard(); + public void setAlphabetShiftLockShiftedKeyboard(); + public void setSymbolsKeyboard(); + public void setSymbolsShiftedKeyboard(); + + /** + * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}. + */ + public void requestUpdatingShiftState(); + + public void startDoubleTapTimer(); + public boolean isInDoubleTapTimeout(); + public void cancelDoubleTapTimer(); + public void startLongPressTimer(int code); + public void cancelLongPressTimer(); + public void hapticAndAudioFeedback(int code); + } + + private final SwitchActions mSwitchActions; + + private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); + private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); + + // TODO: Merge {@link #mSwitchState}, {@link #mIsAlphabetMode}, {@link #mAlphabetShiftState}, + // {@link #mIsSymbolShifted}, {@link #mPrevMainKeyboardWasShiftLocked}, and + // {@link #mPrevSymbolsKeyboardWasShifted} into single state variable. + private static final int SWITCH_STATE_ALPHA = 0; + private static final int SWITCH_STATE_SYMBOL_BEGIN = 1; + private static final int SWITCH_STATE_SYMBOL = 2; + private static final int SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL = 3; + private static final int SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE = 4; + private int mSwitchState = SWITCH_STATE_ALPHA; + private String mLayoutSwitchBackSymbols; + + private boolean mIsAlphabetMode; + private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState(); + private boolean mIsSymbolShifted; + private boolean mPrevMainKeyboardWasShiftLocked; + private boolean mPrevSymbolsKeyboardWasShifted; + + // For handling double tap. + private boolean mIsInAlphabetUnshiftedFromShifted; + private boolean mIsInDoubleTapShiftKey; + + private final SavedKeyboardState mSavedKeyboardState = new SavedKeyboardState(); + + static class SavedKeyboardState { + public boolean mIsValid; + public boolean mIsAlphabetMode; + public boolean mIsAlphabetShiftLocked; + public boolean mIsShifted; + + @Override + public String toString() { + if (!mIsValid) return "INVALID"; + if (mIsAlphabetMode) { + if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED"; + return mIsShifted ? "ALPHABET_SHIFTED" : "ALPHABET"; + } else { + return mIsShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS"; + } + } + } + + public KeyboardState(SwitchActions switchActions) { + mSwitchActions = switchActions; + } + + public void onLoadKeyboard(String layoutSwitchBackSymbols) { + if (DEBUG_EVENT) { + Log.d(TAG, "onLoadKeyboard: " + this); + } + mLayoutSwitchBackSymbols = layoutSwitchBackSymbols; + // Reset alphabet shift state. + mAlphabetShiftState.setShiftLocked(false); + mPrevMainKeyboardWasShiftLocked = false; + mPrevSymbolsKeyboardWasShifted = false; + mShiftKeyState.onRelease(); + mSymbolKeyState.onRelease(); + onRestoreKeyboardState(); + } + + public void onSaveKeyboardState() { + final SavedKeyboardState state = mSavedKeyboardState; + state.mIsAlphabetMode = mIsAlphabetMode; + if (mIsAlphabetMode) { + state.mIsAlphabetShiftLocked = mAlphabetShiftState.isShiftLocked(); + state.mIsShifted = !state.mIsAlphabetShiftLocked + && mAlphabetShiftState.isShiftedOrShiftLocked(); + } else { + state.mIsAlphabetShiftLocked = mPrevMainKeyboardWasShiftLocked; + state.mIsShifted = mIsSymbolShifted; + } + state.mIsValid = true; + if (DEBUG_EVENT) { + Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); + } + } + + private void onRestoreKeyboardState() { + final SavedKeyboardState state = mSavedKeyboardState; + if (DEBUG_EVENT) { + Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); + } + if (!state.mIsValid || state.mIsAlphabetMode) { + setAlphabetKeyboard(); + } else { + if (state.mIsShifted) { + setSymbolsShiftedKeyboard(); + } else { + setSymbolsKeyboard(); + } + } + + if (!state.mIsValid) return; + state.mIsValid = false; + + if (state.mIsAlphabetMode) { + setShiftLocked(state.mIsAlphabetShiftLocked); + if (!state.mIsAlphabetShiftLocked) { + setShifted(state.mIsShifted ? MANUAL_SHIFT : UNSHIFT); + } + } else { + mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked; + } + } + + private static final int UNSHIFT = 0; + private static final int MANUAL_SHIFT = 1; + private static final int AUTOMATIC_SHIFT = 2; + private static final int SHIFT_LOCK_SHIFTED = 3; + + private void setShifted(int shiftMode) { + if (DEBUG_ACTION) { + Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); + } + if (!mIsAlphabetMode) return; + final int prevShiftMode; + if (mAlphabetShiftState.isAutomaticShifted()) { + prevShiftMode = AUTOMATIC_SHIFT; + } else if (mAlphabetShiftState.isManualShifted()) { + prevShiftMode = MANUAL_SHIFT; + } else { + prevShiftMode = UNSHIFT; + } + switch (shiftMode) { + case AUTOMATIC_SHIFT: + mAlphabetShiftState.setAutomaticShifted(); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetAutomaticShiftedKeyboard(); + } + break; + case MANUAL_SHIFT: + mAlphabetShiftState.setShifted(true); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetManualShiftedKeyboard(); + } + break; + case UNSHIFT: + mAlphabetShiftState.setShifted(false); + if (shiftMode != prevShiftMode) { + mSwitchActions.setAlphabetKeyboard(); + } + break; + case SHIFT_LOCK_SHIFTED: + mAlphabetShiftState.setShifted(true); + mSwitchActions.setAlphabetShiftLockShiftedKeyboard(); + break; + } + } + + private void setShiftLocked(boolean shiftLocked) { + if (DEBUG_ACTION) { + Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); + } + if (!mIsAlphabetMode) return; + if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() + || mAlphabetShiftState.isShiftLockShifted())) { + mSwitchActions.setAlphabetShiftLockedKeyboard(); + } + if (!shiftLocked && mAlphabetShiftState.isShiftLocked()) { + mSwitchActions.setAlphabetKeyboard(); + } + mAlphabetShiftState.setShiftLocked(shiftLocked); + } + + private void toggleAlphabetAndSymbols() { + if (DEBUG_ACTION) { + Log.d(TAG, "toggleAlphabetAndSymbols: " + this); + } + if (mIsAlphabetMode) { + mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); + if (mPrevSymbolsKeyboardWasShifted) { + setSymbolsShiftedKeyboard(); + } else { + setSymbolsKeyboard(); + } + mPrevSymbolsKeyboardWasShifted = false; + } else { + mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted; + setAlphabetKeyboard(); + if (mPrevMainKeyboardWasShiftLocked) { + setShiftLocked(true); + } + mPrevMainKeyboardWasShiftLocked = false; + } + } + + private void toggleShiftInSymbols() { + if (mIsSymbolShifted) { + setSymbolsKeyboard(); + } else { + setSymbolsShiftedKeyboard(); + } + } + + private void setAlphabetKeyboard() { + if (DEBUG_ACTION) { + Log.d(TAG, "setAlphabetKeyboard"); + } + mSwitchActions.setAlphabetKeyboard(); + mIsAlphabetMode = true; + mIsSymbolShifted = false; + mSwitchState = SWITCH_STATE_ALPHA; + mSwitchActions.requestUpdatingShiftState(); + } + + private void setSymbolsKeyboard() { + if (DEBUG_ACTION) { + Log.d(TAG, "setSymbolsKeyboard"); + } + mSwitchActions.setSymbolsKeyboard(); + mIsAlphabetMode = false; + mIsSymbolShifted = false; + // Reset alphabet shift state. + mAlphabetShiftState.setShiftLocked(false); + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; + } + + private void setSymbolsShiftedKeyboard() { + if (DEBUG_ACTION) { + Log.d(TAG, "setSymbolsShiftedKeyboard"); + } + mSwitchActions.setSymbolsShiftedKeyboard(); + mIsAlphabetMode = false; + mIsSymbolShifted = true; + // Reset alphabet shift state. + mAlphabetShiftState.setShiftLocked(false); + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; + } + + public void onPressKey(int code) { + if (DEBUG_EVENT) { + Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); + } + if (code == Keyboard.CODE_SHIFT) { + onPressShift(); + } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + onPressSymbol(); + } else { + mSwitchActions.cancelDoubleTapTimer(); + mSwitchActions.cancelLongPressTimer(); + mShiftKeyState.onOtherKeyPressed(); + mSymbolKeyState.onOtherKeyPressed(); + } + } + + public void onReleaseKey(int code, boolean withSliding) { + if (DEBUG_EVENT) { + Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + + " sliding=" + withSliding + " " + this); + } + if (code == Keyboard.CODE_SHIFT) { + onReleaseShift(withSliding); + } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + onReleaseSymbol(withSliding); + } + } + + private void onPressSymbol() { + toggleAlphabetAndSymbols(); + mSymbolKeyState.onPress(); + mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL; + } + + private void onReleaseSymbol(boolean withSliding) { + if (mSymbolKeyState.isChording()) { + // Switch back to the previous keyboard mode if the user chords the mode change key and + // another key, then releases the mode change key. + toggleAlphabetAndSymbols(); + } else if (!withSliding) { + // If the mode change key is being released without sliding, we should forget the + // previous symbols keyboard shift state and simply switch back to symbols layout + // (never symbols shifted) next time the mode gets changed to symbols layout. + mPrevSymbolsKeyboardWasShifted = false; + } + mSymbolKeyState.onRelease(); + } + + public void onLongPressTimeout(int code) { + if (DEBUG_EVENT) { + Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); + } + if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { + if (mAlphabetShiftState.isShiftLocked()) { + setShiftLocked(false); + // Shift key is long pressed while shift locked state, we will toggle back to normal + // state. And mark as if shift key is released. + mShiftKeyState.onRelease(); + } else { + // Shift key is long pressed while shift unlocked state. + setShiftLocked(true); + } + mSwitchActions.hapticAndAudioFeedback(code); + } + } + + public void onUpdateShiftState(boolean autoCaps) { + if (DEBUG_EVENT) { + Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); + } + updateAlphabetShiftState(autoCaps); + } + + private void updateAlphabetShiftState(boolean autoCaps) { + if (!mIsAlphabetMode) return; + if (!mShiftKeyState.isReleasing()) { + // Ignore update shift state event while the shift key is being pressed (including + // chording). + return; + } + if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) { + if (mShiftKeyState.isReleasing() && autoCaps) { + // Only when shift key is releasing, automatic temporary upper case will be set. + setShifted(AUTOMATIC_SHIFT); + } else { + setShifted(mShiftKeyState.isChording() ? MANUAL_SHIFT : UNSHIFT); + } + } + } + + private void onPressShift() { + if (mIsAlphabetMode) { + mIsInDoubleTapShiftKey = mSwitchActions.isInDoubleTapTimeout(); + if (!mIsInDoubleTapShiftKey) { + // This is first tap. + mSwitchActions.startDoubleTapTimer(); + } + if (mIsInDoubleTapShiftKey) { + if (mAlphabetShiftState.isManualShifted() || mIsInAlphabetUnshiftedFromShifted) { + // Shift key has been double tapped while in manual shifted or automatic + // shifted state. + setShiftLocked(true); + } else { + // Shift key has been double tapped while in normal state. This is the second + // tap to disable shift locked state, so just ignore this. + } + } else { + if (mAlphabetShiftState.isShiftLocked()) { + // Shift key is pressed while shift locked state, we will treat this state as + // shift lock shifted state and mark as if shift key pressed while normal state. + setShifted(SHIFT_LOCK_SHIFTED); + mShiftKeyState.onPress(); + } else if (mAlphabetShiftState.isAutomaticShifted()) { + // Shift key is pressed while automatic shifted, we have to move to manual + // shifted. + setShifted(MANUAL_SHIFT); + mShiftKeyState.onPress(); + } else if (mAlphabetShiftState.isShiftedOrShiftLocked()) { + // In manual shifted state, we just record shift key has been pressing while + // shifted state. + mShiftKeyState.onPressOnShifted(); + } else { + // In base layout, chording or manual shifted mode is started. + setShifted(MANUAL_SHIFT); + mShiftKeyState.onPress(); + } + mSwitchActions.startLongPressTimer(Keyboard.CODE_SHIFT); + } + } else { + // In symbol mode, just toggle symbol and symbol more keyboard. + toggleShiftInSymbols(); + mSwitchState = SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; + mShiftKeyState.onPress(); + } + } + + private void onReleaseShift(boolean withSliding) { + if (mIsAlphabetMode) { + final boolean isShiftLocked = mAlphabetShiftState.isShiftLocked(); + mIsInAlphabetUnshiftedFromShifted = false; + if (mIsInDoubleTapShiftKey) { + // Double tap shift key has been handled in {@link #onPressShift}, so that just + // ignore this release shift key here. + mIsInDoubleTapShiftKey = false; + } else if (mShiftKeyState.isChording()) { + if (mAlphabetShiftState.isShiftLockShifted()) { + // After chording input while shift locked state. + setShiftLocked(true); + } else { + // After chording input while normal state. + setShifted(UNSHIFT); + } + } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) { + // In shift locked state, shift has been pressed and slid out to other key. + setShiftLocked(true); + } else if (isShiftLocked && !mAlphabetShiftState.isShiftLockShifted() + && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted()) + && !withSliding) { + // Shift has been long pressed, ignore this release. + } else if (isShiftLocked && !mShiftKeyState.isIgnoring() && !withSliding) { + // Shift has been pressed without chording while shift locked state. + setShiftLocked(false); + } else if (mAlphabetShiftState.isShiftedOrShiftLocked() + && mShiftKeyState.isPressingOnShifted() && !withSliding) { + // Shift has been pressed without chording while shifted state. + setShifted(UNSHIFT); + mIsInAlphabetUnshiftedFromShifted = true; + } else if (mAlphabetShiftState.isManualShiftedFromAutomaticShifted() + && mShiftKeyState.isPressing() && !withSliding) { + // Shift has been pressed without chording while manual shifted transited from + // automatic shifted + setShifted(UNSHIFT); + mIsInAlphabetUnshiftedFromShifted = true; + } + } else { + // In symbol mode, switch back to the previous keyboard mode if the user chords the + // shift key and another key, then releases the shift key. + if (mShiftKeyState.isChording()) { + toggleShiftInSymbols(); + } + } + mShiftKeyState.onRelease(); + } + + public void onCancelInput(boolean isSinglePointer) { + if (DEBUG_EVENT) { + Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); + } + // Switch back to the previous keyboard mode if the user cancels sliding input. + if (isSinglePointer) { + if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { + toggleAlphabetAndSymbols(); + } else if (mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE) { + toggleShiftInSymbols(); + } + } + } + + public boolean isInMomentarySwitchState() { + return mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL + || mSwitchState == SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE; + } + + private static boolean isSpaceCharacter(int c) { + return c == Keyboard.CODE_SPACE || c == Keyboard.CODE_ENTER; + } + + private boolean isLayoutSwitchBackCharacter(int c) { + if (TextUtils.isEmpty(mLayoutSwitchBackSymbols)) return false; + if (mLayoutSwitchBackSymbols.indexOf(c) >= 0) return true; + return false; + } + + public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) { + if (DEBUG_EVENT) { + Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code) + + " single=" + isSinglePointer + + " autoCaps=" + autoCaps + " " + this); + } + + switch (mSwitchState) { + case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: + if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { + // Detected only the mode change key has been pressed, and then released. + if (mIsAlphabetMode) { + mSwitchState = SWITCH_STATE_ALPHA; + } else { + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; + } + } else if (isSinglePointer) { + // Switch back to the previous keyboard mode if the user pressed the mode change key + // and slid to other key, then released the finger. + // If the user cancels the sliding input, switching back to the previous keyboard + // mode is handled by {@link #onCancelInput}. + toggleAlphabetAndSymbols(); + } + break; + case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: + if (code == Keyboard.CODE_SHIFT) { + // Detected only the shift key has been pressed on symbol layout, and then released. + mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; + } else if (isSinglePointer) { + // Switch back to the previous keyboard mode if the user pressed the shift key on + // symbol mode and slid to other key, then released the finger. + toggleShiftInSymbols(); + mSwitchState = SWITCH_STATE_SYMBOL; + } + break; + case SWITCH_STATE_SYMBOL_BEGIN: + if (!isSpaceCharacter(code) && (Keyboard.isLetterCode(code) + || code == Keyboard.CODE_OUTPUT_TEXT)) { + mSwitchState = SWITCH_STATE_SYMBOL; + } + // Switch back to alpha keyboard mode immediately if user types one of the switch back + // characters. + if (isLayoutSwitchBackCharacter(code)) { + toggleAlphabetAndSymbols(); + mPrevSymbolsKeyboardWasShifted = false; + } + break; + case SWITCH_STATE_SYMBOL: + // Switch back to alpha keyboard mode if user types one or more non-space/enter + // characters followed by a space/enter or one of the switch back characters. + if (isSpaceCharacter(code) || isLayoutSwitchBackCharacter(code)) { + toggleAlphabetAndSymbols(); + mPrevSymbolsKeyboardWasShifted = false; + } + break; + } + + // If the code is a letter, update keyboard shift state. + if (Keyboard.isLetterCode(code)) { + updateAlphabetShiftState(autoCaps); + } + } + + private static String shiftModeToString(int shiftMode) { + switch (shiftMode) { + case UNSHIFT: return "UNSHIFT"; + case MANUAL_SHIFT: return "MANUAL"; + case AUTOMATIC_SHIFT: return "AUTOMATIC"; + default: return null; + } + } + + private static String switchStateToString(int switchState) { + switch (switchState) { + case SWITCH_STATE_ALPHA: return "ALPHA"; + case SWITCH_STATE_SYMBOL_BEGIN: return "SYMBOL-BEGIN"; + case SWITCH_STATE_SYMBOL: return "SYMBOL"; + case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: return "MOMENTARY-ALPHA-SYMBOL"; + case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE: return "MOMENTARY-SYMBOL-MORE"; + default: return null; + } + } + + @Override + public String toString() { + return "[keyboard=" + (mIsAlphabetMode ? mAlphabetShiftState.toString() + : (mIsSymbolShifted ? "SYMBOLS_SHIFTED" : "SYMBOLS")) + + " shift=" + mShiftKeyState + + " symbol=" + mSymbolKeyState + + " switch=" + switchStateToString(mSwitchState) + "]"; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java index dae73c4e4..b39b97720 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ModifierKeyState.java @@ -18,15 +18,13 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -import com.android.inputmethod.keyboard.KeyboardSwitcher; - -public class ModifierKeyState { - protected static final String TAG = "ModifierKeyState"; - protected static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE; +/* package */ class ModifierKeyState { + protected static final String TAG = ModifierKeyState.class.getSimpleName(); + protected static final boolean DEBUG = false; protected static final int RELEASING = 0; protected static final int PRESSING = 1; - protected static final int MOMENTARY = 2; + protected static final int CHORDING = 2; protected final String mName; protected int mState = RELEASING; @@ -52,7 +50,7 @@ public class ModifierKeyState { public void onOtherKeyPressed() { final int oldState = mState; if (oldState == PRESSING) - mState = MOMENTARY; + mState = CHORDING; if (DEBUG) Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } @@ -65,8 +63,8 @@ public class ModifierKeyState { return mState == RELEASING; } - public boolean isMomentary() { - return mState == MOMENTARY; + public boolean isChording() { + return mState == CHORDING; } @Override @@ -78,7 +76,7 @@ public class ModifierKeyState { switch (state) { case RELEASING: return "RELEASING"; case PRESSING: return "PRESSING"; - case MOMENTARY: return "MOMENTARY"; + case CHORDING: return "CHORDING"; default: return "UNKNOWN"; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java deleted file mode 100644 index a490b0ad6..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.content.res.Resources; -import android.text.TextUtils; -import android.util.Log; - -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.R; - -import java.util.ArrayList; - -/** - * String parser of moreKeys attribute of Key. - * The string is comma separated texts each of which represents one "more key". - * Each "more key" specification is one of the following: - * - A single letter (Letter) - * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText). - * - Icon followed by keyOutputText or code (@icon/icon_number|@integer/key_code) - * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' - * character. - * Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well. - * See {@link KeyboardIconsSet} about icon_number. - */ -public class MoreKeySpecParser { - private static final String TAG = MoreKeySpecParser.class.getSimpleName(); - - private static final char ESCAPE = '\\'; - private static final String LABEL_END = "|"; - private static final String PREFIX_AT = "@"; - private static final String PREFIX_ICON = PREFIX_AT + "icon/"; - private static final String PREFIX_CODE = PREFIX_AT + "integer/"; - - private MoreKeySpecParser() { - // Intentional empty constructor for utility class. - } - - private static boolean hasIcon(String moreKeySpec) { - if (moreKeySpec.startsWith(PREFIX_ICON)) { - final int end = indexOfLabelEnd(moreKeySpec, 0); - if (end > 0) - return true; - throw new MoreKeySpecParserError("outputText or code not specified: " + moreKeySpec); - } - return false; - } - - private static boolean hasCode(String moreKeySpec) { - final int end = indexOfLabelEnd(moreKeySpec, 0); - if (end > 0 && end + 1 < moreKeySpec.length() - && moreKeySpec.substring(end + 1).startsWith(PREFIX_CODE)) { - return true; - } - return false; - } - - private static String parseEscape(String text) { - if (text.indexOf(ESCAPE) < 0) - return text; - final int length = text.length(); - final StringBuilder sb = new StringBuilder(); - for (int pos = 0; pos < length; pos++) { - final char c = text.charAt(pos); - if (c == ESCAPE && pos + 1 < length) { - sb.append(text.charAt(++pos)); - } else { - sb.append(c); - } - } - return sb.toString(); - } - - private static int indexOfLabelEnd(String moreKeySpec, int start) { - if (moreKeySpec.indexOf(ESCAPE, start) < 0) { - final int end = moreKeySpec.indexOf(LABEL_END, start); - if (end == 0) - throw new MoreKeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec); - return end; - } - final int length = moreKeySpec.length(); - for (int pos = start; pos < length; pos++) { - final char c = moreKeySpec.charAt(pos); - if (c == ESCAPE && pos + 1 < length) { - pos++; - } else if (moreKeySpec.startsWith(LABEL_END, pos)) { - return pos; - } - } - return -1; - } - - public static String getLabel(String moreKeySpec) { - if (hasIcon(moreKeySpec)) - return null; - final int end = indexOfLabelEnd(moreKeySpec, 0); - final String label = (end > 0) ? parseEscape(moreKeySpec.substring(0, end)) - : parseEscape(moreKeySpec); - if (TextUtils.isEmpty(label)) - throw new MoreKeySpecParserError("Empty label: " + moreKeySpec); - return label; - } - - public static String getOutputText(String moreKeySpec) { - if (hasCode(moreKeySpec)) - return null; - final int end = indexOfLabelEnd(moreKeySpec, 0); - if (end > 0) { - if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) - throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": " - + moreKeySpec); - final String outputText = parseEscape(moreKeySpec.substring(end + LABEL_END.length())); - if (!TextUtils.isEmpty(outputText)) - return outputText; - throw new MoreKeySpecParserError("Empty outputText: " + moreKeySpec); - } - final String label = getLabel(moreKeySpec); - if (label == null) - throw new MoreKeySpecParserError("Empty label: " + moreKeySpec); - // Code is automatically generated for one letter label. See {@link getCode()}. - if (label.length() == 1) - return null; - return label; - } - - public static int getCode(Resources res, String moreKeySpec) { - if (hasCode(moreKeySpec)) { - final int end = indexOfLabelEnd(moreKeySpec, 0); - if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) - throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); - final int resId = getResourceId(res, - moreKeySpec.substring(end + LABEL_END.length() + PREFIX_AT.length())); - final int code = res.getInteger(resId); - return code; - } - if (indexOfLabelEnd(moreKeySpec, 0) > 0) - return Keyboard.CODE_DUMMY; - final String label = getLabel(moreKeySpec); - // Code is automatically generated for one letter label. - if (label != null && label.length() == 1) - return label.charAt(0); - return Keyboard.CODE_DUMMY; - } - - public static int getIconId(String moreKeySpec) { - if (hasIcon(moreKeySpec)) { - int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length() + 1); - final String iconId = moreKeySpec.substring(PREFIX_ICON.length(), end); - try { - return Integer.valueOf(iconId); - } catch (NumberFormatException e) { - Log.w(TAG, "illegal icon id specified: " + iconId); - return KeyboardIconsSet.ICON_UNDEFINED; - } - } - return KeyboardIconsSet.ICON_UNDEFINED; - } - - private static int getResourceId(Resources res, String name) { - String packageName = res.getResourcePackageName(R.string.english_ime_name); - int resId = res.getIdentifier(name, null, packageName); - if (resId == 0) - throw new MoreKeySpecParserError("Unknown resource: " + name); - return resId; - } - - @SuppressWarnings("serial") - public static class MoreKeySpecParserError extends RuntimeException { - public MoreKeySpecParserError(String message) { - super(message); - } - } - - public interface CodeFilter { - public boolean shouldFilterOut(int code); - } - - public static final CodeFilter DIGIT_FILTER = new CodeFilter() { - @Override - public boolean shouldFilterOut(int code) { - return Character.isDigit(code); - } - }; - - public static CharSequence[] filterOut(Resources res, CharSequence[] moreKeys, - CodeFilter filter) { - if (moreKeys == null || moreKeys.length < 1) { - return null; - } - if (moreKeys.length == 1 - && filter.shouldFilterOut(getCode(res, moreKeys[0].toString()))) { - return null; - } - ArrayList<CharSequence> filtered = null; - for (int i = 0; i < moreKeys.length; i++) { - final CharSequence moreKeySpec = moreKeys[i]; - if (filter.shouldFilterOut(getCode(res, moreKeySpec.toString()))) { - if (filtered == null) { - filtered = new ArrayList<CharSequence>(); - for (int j = 0; j < i; j++) { - filtered.add(moreKeys[j]); - } - } - } else if (filtered != null) { - filtered.add(moreKeySpec); - } - } - if (filtered == null) { - return moreKeys; - } - if (filtered.size() == 0) { - return null; - } - return filtered.toArray(new CharSequence[filtered.size()]); - } -} diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java index 08e7a7a4e..5db65c660 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java @@ -16,29 +16,45 @@ package com.android.inputmethod.keyboard.internal; +import android.util.Log; + +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.PointerTracker; +import java.util.Iterator; import java.util.LinkedList; public class PointerTrackerQueue { + private static final String TAG = PointerTrackerQueue.class.getSimpleName(); + private static final boolean DEBUG = false; + private final LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>(); public synchronized void add(PointerTracker tracker) { mQueue.add(tracker); } - public synchronized void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) { - if (mQueue.lastIndexOf(tracker) < 0) { + public synchronized void remove(PointerTracker tracker) { + mQueue.remove(tracker); + } + + public synchronized void releaseAllPointersOlderThan(PointerTracker tracker, + long eventTime) { + if (DEBUG) { + Log.d(TAG, "releaseAllPoniterOlderThan: [" + tracker.mPointerId + "] " + this); + } + if (!mQueue.contains(tracker)) { return; } - final LinkedList<PointerTracker> queue = mQueue; - int oldestPos = 0; - for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) { - if (t.isModifier()) { - oldestPos++; - } else { + final Iterator<PointerTracker> it = mQueue.iterator(); + while (it.hasNext()) { + final PointerTracker t = it.next(); + if (t == tracker) { + break; + } + if (!t.isModifier()) { t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); - queue.remove(oldestPos); + it.remove(); } } } @@ -48,22 +64,23 @@ public class PointerTrackerQueue { } public synchronized void releaseAllPointersExcept(PointerTracker tracker, long eventTime) { - for (PointerTracker t : mQueue) { - if (t == tracker) { - continue; + if (DEBUG) { + if (tracker == null) { + Log.d(TAG, "releaseAllPoniters: " + this); + } else { + Log.d(TAG, "releaseAllPoniterExcept: [" + tracker.mPointerId + "] " + this); } - t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); } - mQueue.clear(); - if (tracker != null) { - mQueue.add(tracker); + final Iterator<PointerTracker> it = mQueue.iterator(); + while (it.hasNext()) { + final PointerTracker t = it.next(); + if (t != tracker) { + t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); + it.remove(); + } } } - public synchronized void remove(PointerTracker tracker) { - mQueue.remove(tracker); - } - public synchronized boolean isAnyInSlidingKeyInput() { for (final PointerTracker tracker : mQueue) { if (tracker.isInSlidingKeyInput()) { @@ -75,13 +92,13 @@ public class PointerTrackerQueue { @Override public String toString() { - StringBuilder sb = new StringBuilder("["); - for (PointerTracker tracker : mQueue) { - if (sb.length() > 1) + final StringBuilder sb = new StringBuilder(); + for (final PointerTracker tracker : mQueue) { + if (sb.length() > 0) sb.append(" "); - sb.append(String.format("%d", tracker.mPointerId)); + sb.append("[" + tracker.mPointerId + " " + + Keyboard.printableCode(tracker.getKey().mCode) + "]"); } - sb.append("]"); return sb.toString(); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java index 6617b917f..edb40c8e7 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/ShiftKeyState.java @@ -18,7 +18,7 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; -public class ShiftKeyState extends ModifierKeyState { +/* package */ class ShiftKeyState extends ModifierKeyState { private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked private static final int IGNORING = 4; @@ -30,7 +30,7 @@ public class ShiftKeyState extends ModifierKeyState { public void onOtherKeyPressed() { int oldState = mState; if (oldState == PRESSING) { - mState = MOMENTARY; + mState = CHORDING; } else if (oldState == PRESSING_ON_SHIFTED) { mState = IGNORING; } diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java new file mode 100644 index 000000000..9c5ccc76b --- /dev/null +++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java @@ -0,0 +1,104 @@ +/* + * 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 android.media.AudioManager; +import android.view.HapticFeedbackConstants; +import android.view.View; + +import com.android.inputmethod.compat.VibratorCompatWrapper; +import com.android.inputmethod.keyboard.Keyboard; + +/** + * This class gathers audio feedback and haptic feedback functions. + * + * It offers a consistent and simple interface that allows LatinIME to forget about the + * complexity of settings and the like. + */ +public class AudioAndHapticFeedbackManager { + final private SettingsValues mSettingsValues; + final private AudioManager mAudioManager; + final private VibratorCompatWrapper mVibrator; + private boolean mSoundOn; + + public AudioAndHapticFeedbackManager(final LatinIME latinIme, + final SettingsValues settingsValues) { + mSettingsValues = settingsValues; + mVibrator = VibratorCompatWrapper.getInstance(latinIme); + mAudioManager = (AudioManager) latinIme.getSystemService(Context.AUDIO_SERVICE); + mSoundOn = reevaluateIfSoundIsOn(); + } + + public void hapticAndAudioFeedback(final int primaryCode, + final View viewToPerformHapticFeedbackOn) { + vibrate(viewToPerformHapticFeedbackOn); + playKeyClick(primaryCode); + } + + private boolean reevaluateIfSoundIsOn() { + if (!mSettingsValues.mSoundOn || mAudioManager == null) { + return false; + } else { + return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL; + } + } + + private void playKeyClick(int primaryCode) { + // if mAudioManager is null, we can't play a sound anyway, so return + if (mAudioManager == null) return; + if (mSoundOn) { + final int sound; + switch (primaryCode) { + case Keyboard.CODE_DELETE: + sound = AudioManager.FX_KEYPRESS_DELETE; + break; + case Keyboard.CODE_ENTER: + sound = AudioManager.FX_KEYPRESS_RETURN; + break; + case Keyboard.CODE_SPACE: + sound = AudioManager.FX_KEYPRESS_SPACEBAR; + break; + default: + sound = AudioManager.FX_KEYPRESS_STANDARD; + break; + } + mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume); + } + } + + // TODO: make this private when LatinIME does not call it any more + public void vibrate(final View viewToPerformHapticFeedbackOn) { + if (!mSettingsValues.mVibrateOn) { + return; + } + if (mSettingsValues.mKeypressVibrationDuration < 0) { + // Go ahead with the system default + if (viewToPerformHapticFeedbackOn != null) { + viewToPerformHapticFeedbackOn.performHapticFeedback( + HapticFeedbackConstants.KEYBOARD_TAP, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } + } else if (mVibrator != null) { + mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration); + } + } + + public void onRingerModeChanged() { + mSoundOn = reevaluateIfSoundIsOn(); + } +} diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index 485ec511f..9c35f8f6f 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -25,44 +25,25 @@ import java.util.Map; public class AutoCorrection { private static final boolean DBG = LatinImeLogger.sDBG; private static final String TAG = AutoCorrection.class.getSimpleName(); - private boolean mHasAutoCorrection; - private CharSequence mAutoCorrectionWord; - private double mNormalizedScore; - public void init() { - mHasAutoCorrection = false; - mAutoCorrectionWord = null; - mNormalizedScore = Integer.MIN_VALUE; + private AutoCorrection() { + // Purely static class: can't instantiate. } - public boolean hasAutoCorrection() { - return mHasAutoCorrection; - } - - public CharSequence getAutoCorrectionWord() { - return mAutoCorrectionWord; - } - - public double getNormalizedScore() { - return mNormalizedScore; - } - - public void updateAutoCorrectionStatus(Map<String, Dictionary> dictionaries, + public static CharSequence computeAutoCorrectionWord(Map<String, Dictionary> dictionaries, WordComposer wordComposer, ArrayList<CharSequence> suggestions, int[] sortedScores, - CharSequence typedWord, double autoCorrectionThreshold, int correctionMode, + CharSequence consideredWord, double autoCorrectionThreshold, CharSequence whitelistedWord) { if (hasAutoCorrectionForWhitelistedWord(whitelistedWord)) { - mHasAutoCorrection = true; - mAutoCorrectionWord = whitelistedWord; - } else if (hasAutoCorrectionForTypedWord( - dictionaries, wordComposer, suggestions, typedWord, correctionMode)) { - mHasAutoCorrection = true; - mAutoCorrectionWord = typedWord; - } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions, correctionMode, - sortedScores, typedWord, autoCorrectionThreshold)) { - mHasAutoCorrection = true; - mAutoCorrectionWord = suggestions.get(0); + return whitelistedWord; + } else if (hasAutoCorrectionForConsideredWord( + dictionaries, wordComposer, suggestions, consideredWord)) { + return consideredWord; + } else if (hasAutoCorrectionForBinaryDictionary(wordComposer, suggestions, + sortedScores, consideredWord, autoCorrectionThreshold)) { + return suggestions.get(0); } + return null; } public static boolean isValidWord( @@ -74,6 +55,14 @@ public class AutoCorrection { for (final String key : dictionaries.keySet()) { if (key.equals(Suggest.DICT_KEY_WHITELIST)) continue; final Dictionary dictionary = dictionaries.get(key); + // It's unclear how realistically 'dictionary' can be null, but the monkey is somehow + // managing to get null in here. Presumably the language is changing to a language with + // no main dictionary and the monkey manages to type a whole word before the thread + // that reads the dictionary is started or something? + // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and + // would be immutable once it's finished initializing, but concretely a null test is + // probably good enough for the time being. + if (null == dictionary) continue; if (dictionary.isValidWord(word) || (ignoreCase && dictionary.isValidWord(lowerCasedWord))) { return true; @@ -98,34 +87,31 @@ public class AutoCorrection { return whiteListedWord != null; } - private boolean hasAutoCorrectionForTypedWord(Map<String, Dictionary> dictionaries, - WordComposer wordComposer, ArrayList<CharSequence> suggestions, CharSequence typedWord, - int correctionMode) { - if (TextUtils.isEmpty(typedWord)) return false; - boolean allowsAutoCorrect = allowsToBeAutoCorrected(dictionaries, typedWord, false); - return wordComposer.size() > 1 && suggestions.size() > 0 && !allowsAutoCorrect - && (correctionMode == Suggest.CORRECTION_FULL - || correctionMode == Suggest.CORRECTION_FULL_BIGRAM); + private static boolean hasAutoCorrectionForConsideredWord(Map<String, Dictionary> dictionaries, + WordComposer wordComposer, ArrayList<CharSequence> suggestions, + CharSequence consideredWord) { + if (TextUtils.isEmpty(consideredWord)) return false; + return wordComposer.size() > 1 && suggestions.size() > 0 + && !allowsToBeAutoCorrected(dictionaries, consideredWord, false); } - private boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer, - ArrayList<CharSequence> suggestions, int correctionMode, int[] sortedScores, - CharSequence typedWord, double autoCorrectionThreshold) { - if (wordComposer.size() > 1 && (correctionMode == Suggest.CORRECTION_FULL - || correctionMode == Suggest.CORRECTION_FULL_BIGRAM) - && typedWord != null && suggestions.size() > 0 && sortedScores.length > 0) { + private static boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer, + ArrayList<CharSequence> suggestions, int[] sortedScores, + CharSequence consideredWord, double autoCorrectionThreshold) { + if (wordComposer.size() > 1 && suggestions.size() > 0 && sortedScores.length > 0) { final CharSequence autoCorrectionSuggestion = suggestions.get(0); final int autoCorrectionSuggestionScore = sortedScores[0]; // TODO: when the normalized score of the first suggestion is nearly equals to // the normalized score of the second suggestion, behave less aggressive. - mNormalizedScore = Utils.calcNormalizedScore( - typedWord,autoCorrectionSuggestion, autoCorrectionSuggestionScore); + final double normalizedScore = BinaryDictionary.calcNormalizedScore( + consideredWord.toString(), autoCorrectionSuggestion.toString(), + autoCorrectionSuggestionScore); if (DBG) { - Log.d(TAG, "Normalized " + typedWord + "," + autoCorrectionSuggestion + "," - + autoCorrectionSuggestionScore + ", " + mNormalizedScore + Log.d(TAG, "Normalized " + consideredWord + "," + autoCorrectionSuggestion + "," + + autoCorrectionSuggestionScore + ", " + normalizedScore + "(" + autoCorrectionThreshold + ")"); } - if (mNormalizedScore >= autoCorrectionThreshold) { + if (normalizedScore >= autoCorrectionThreshold) { if (DBG) { Log.d(TAG, "Auto corrected by S-threshold."); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index b9fd57434..31ff4e7b4 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -46,7 +46,7 @@ public class BinaryDictionary extends Dictionary { private static final int TYPED_LETTER_MULTIPLIER = 2; private int mDicTypeId; - private int mNativeDict; + private long mNativeDict; private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; @@ -104,20 +104,24 @@ public class BinaryDictionary extends Dictionary { } static { - Utils.loadNativeLibrary(); + JniUtils.loadNativeLibrary(); } - private native int openNative(String sourceDir, long dictOffset, long dictSize, + private native long openNative(String sourceDir, long dictOffset, long dictSize, int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives); - private native void closeNative(int dict); - private native boolean isValidWordNative(int nativeData, char[] word, int wordLength); - private native int getSuggestionsNative(int dict, int proximityInfo, int[] xCoordinates, + private native void closeNative(long dict); + private native boolean isValidWordNative(long dict, char[] word, int wordLength); + private native int getSuggestionsNative(long dict, long proximityInfo, int[] xCoordinates, int[] yCoordinates, int[] inputCodes, int codesSize, int flags, char[] outputChars, int[] scores); - private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength, + private native int getBigramsNative(long dict, char[] prevWord, int prevWordLength, int[] inputCodes, int inputCodesLength, char[] outputChars, int[] scores, int maxWordLength, int maxBigrams, int maxAlternatives); + private static native double calcNormalizedScoreNative( + char[] before, int beforeLength, char[] after, int afterLength, int score); + private static native int editDistanceNative( + char[] before, int beforeLength, char[] after, int afterLength); private final void loadDictionary(String path, long startOffset, long length) { mNativeDict = openNative(path, startOffset, length, @@ -135,22 +139,19 @@ public class BinaryDictionary extends Dictionary { Arrays.fill(mBigramScores, 0); int codesSize = codes.size(); - if (codesSize <= 0) { - // Do not return bigrams from BinaryDictionary when nothing was typed. - // Only use user-history bigrams (or whatever other bigram dictionaries decide). - return; - } Arrays.fill(mInputCodes, -1); - int[] alternatives = codes.getCodesAt(0); - System.arraycopy(alternatives, 0, mInputCodes, 0, - Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); + if (codesSize > 0) { + int[] alternatives = codes.getCodesAt(0); + System.arraycopy(alternatives, 0, mInputCodes, 0, + Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); + } int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS, MAX_PROXIMITY_CHARS_SIZE); for (int j = 0; j < count; ++j) { - if (mBigramScores[j] < 1) break; + if (codesSize > 0 && mBigramScores[j] < 1) break; final int start = j * MAX_WORD_LENGTH; int len = 0; while (len < MAX_WORD_LENGTH && mOutputChars_bigrams[start + len] != 0) { @@ -158,7 +159,7 @@ public class BinaryDictionary extends Dictionary { } if (len > 0) { callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j], - mDicTypeId, DataType.BIGRAM); + mDicTypeId, Dictionary.BIGRAM); } } } @@ -178,7 +179,7 @@ public class BinaryDictionary extends Dictionary { } if (len > 0) { callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId, - DataType.UNIGRAM); + Dictionary.UNIGRAM); } } } @@ -211,6 +212,16 @@ public class BinaryDictionary extends Dictionary { mFlags, outputChars, scores); } + public static double calcNormalizedScore(String before, String after, int score) { + return calcNormalizedScoreNative(before.toCharArray(), before.length(), + after.toCharArray(), after.length(), score); + } + + public static int editDistance(String before, String after) { + return editDistanceNative( + before.toCharArray(), before.length(), after.toCharArray(), after.length()); + } + @Override public boolean isValidWord(CharSequence word) { if (word == null) return false; diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index b333e4873..79441c557 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -75,7 +75,8 @@ class BinaryDictionaryGetter { // This assumes '%' is fully available as a non-separator, normal // character in a file name. This is probably true for all file systems. final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < name.length(); ++i) { + final int nameLength = name.length(); + for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) { final int codePoint = name.codePointAt(i); if (isFileNameCharacter(codePoint)) { sb.appendCodePoint(codePoint); @@ -92,7 +93,8 @@ class BinaryDictionaryGetter { */ private static String getWordListIdFromFileName(final String fname) { final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < fname.length(); ++i) { + final int fnameLength = fname.length(); + for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) { final int codePoint = fname.codePointAt(i); if ('%' != codePoint) { sb.appendCodePoint(codePoint); diff --git a/java/src/com/android/inputmethod/latin/ComposingStateManager.java b/java/src/com/android/inputmethod/latin/ComposingStateManager.java deleted file mode 100644 index 8811f2023..000000000 --- a/java/src/com/android/inputmethod/latin/ComposingStateManager.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2011 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.util.Log; - -public class ComposingStateManager { - private static final String TAG = ComposingStateManager.class.getSimpleName(); - private static final ComposingStateManager sInstance = new ComposingStateManager(); - private boolean mAutoCorrectionIndicatorOn; - private boolean mIsComposing; - - public static ComposingStateManager getInstance() { - return sInstance; - } - - private ComposingStateManager() { - mAutoCorrectionIndicatorOn = false; - mIsComposing = false; - } - - public synchronized void onStartComposingText() { - if (!mIsComposing) { - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Start composing text."); - } - mAutoCorrectionIndicatorOn = false; - mIsComposing = true; - } - } - - public synchronized void onFinishComposingText() { - if (mIsComposing) { - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Finish composing text."); - } - mAutoCorrectionIndicatorOn = false; - mIsComposing = false; - } - } - - public synchronized boolean isAutoCorrectionIndicatorOn() { - return mAutoCorrectionIndicatorOn; - } - - public synchronized void setAutoCorrectionIndicatorOn(boolean on) { - // Auto-correction indicator should be specified only when the current state is "composing". - if (!mIsComposing) return; - if (LatinImeLogger.sDBG) { - Log.i(TAG, "Set auto correction Indicator: " + on); - } - mAutoCorrectionIndicatorOn = on; - } -} diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index 2f1e7c2b8..870b33f9a 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -25,11 +25,14 @@ import android.preference.CheckBoxPreference; import android.preference.PreferenceActivity; import android.util.Log; +import com.android.inputmethod.keyboard.KeyboardSwitcher; + public class DebugSettings extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "DebugSettings"; private static final String DEBUG_MODE_KEY = "debug_mode"; + public static final String FORCE_NON_DISTINCT_MULTITOUCH_KEY = "force_non_distinct_multitouch"; private boolean mServiceNeedsRestart = false; private CheckBoxPreference mDebugMode; @@ -60,6 +63,9 @@ public class DebugSettings extends PreferenceActivity updateDebugMode(); mServiceNeedsRestart = true; } + } else if (key.equals(FORCE_NON_DISTINCT_MULTITOUCH_KEY) + || key.equals(KeyboardSwitcher.PREF_KEYBOARD_LAYOUT)) { + mServiceNeedsRestart = true; } } diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index c35b42877..79bf33850 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,9 +33,8 @@ public abstract class Dictionary { */ protected static final int FULL_WORD_SCORE_MULTIPLIER = 2; - public static enum DataType { - UNIGRAM, BIGRAM - } + public static final int UNIGRAM = 0; + public static final int BIGRAM = 1; /** * Interface to be implemented by classes requesting words to be fetched from the dictionary. @@ -51,11 +50,11 @@ public abstract class Dictionary { * @param score the score of occurrence. This is normalized between 1 and 255, but * can exceed those limits * @param dicTypeId of the dictionary where word was from - * @param dataType tells type of this data + * @param dataType tells type of this data, either UNIGRAM or BIGRAM * @return true if the word was added, false if no more words are required */ boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId, - DataType dataType); + int dataType); } /** @@ -64,7 +63,7 @@ public abstract class Dictionary { * @param composer the key sequence to match * @param callback the callback object to send matched words to as possible candidates * @param proximityInfo the object for key proximity. May be ignored by some implementations. - * @see WordCallback#addWord(char[], int, int, int, int, DataType) + * @see WordCallback#addWord(char[], int, int, int, int, int) */ abstract public void getWords(final WordComposer composer, final WordCallback callback, final ProximityInfo proximityInfo); diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java index 739153044..c19a5a718 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -18,6 +18,8 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.ProximityInfo; +import android.util.Log; + import java.util.Collection; import java.util.Collections; import java.util.List; @@ -27,7 +29,7 @@ import java.util.concurrent.CopyOnWriteArrayList; * Class for a collection of dictionaries that behave like one dictionary. */ public class DictionaryCollection extends Dictionary { - + private final String TAG = DictionaryCollection.class.getSimpleName(); protected final List<Dictionary> mDictionaries; public DictionaryCollection() { @@ -75,7 +77,21 @@ public class DictionaryCollection extends Dictionary { dict.close(); } - public void addDictionary(Dictionary newDict) { - if (null != newDict) mDictionaries.add(newDict); + // Warning: this is not thread-safe. Take necessary precaution when calling. + public void addDictionary(final Dictionary newDict) { + if (null == newDict) return; + if (mDictionaries.contains(newDict)) { + Log.w(TAG, "This collection already contains this dictionary: " + newDict); + } + mDictionaries.add(newDict); + } + + // Warning: this is not thread-safe. Take necessary precaution when calling. + public void removeDictionary(final Dictionary dict) { + if (mDictionaries.contains(dict)) { + mDictionaries.remove(dict); + } else { + Log.w(TAG, "This collection does not contain this dictionary: " + dict); + } } } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 1607f86a8..7a81f7bd5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -164,7 +164,7 @@ public class DictionaryFactory { final Resources res = context.getResources(); final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - final int resourceId = Utils.getMainDictionaryResourceId(res); + final int resourceId = getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); final boolean hasDictionary = isFullDictionary(afd); try { @@ -182,7 +182,7 @@ public class DictionaryFactory { final Resources res = context.getResources(); final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - final int resourceId = Utils.getMainDictionaryResourceId(res); + final int resourceId = getMainDictionaryResourceId(res); final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) ? afd.getLength() @@ -209,4 +209,14 @@ public class DictionaryFactory { protected static boolean isFullDictionary(final AssetFileDescriptor afd) { return (afd != null && afd.getLength() > PLACEHOLDER_LENGTH); } + + /** + * Returns a main dictionary resource id + * @return main dictionary resource id + */ + public static int getMainDictionaryResourceId(Resources res) { + final String MAIN_DIC_NAME = "main"; + String packageName = LatinIME.class.getPackage().getName(); + return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); + } } diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 634dbbdfc..1e8ad1840 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -87,23 +87,6 @@ public class EditingUtils { } /** - * Removes the word surrounding the cursor. Parameters are identical to - * getWordAtCursor. - */ - public static void deleteWordAtCursor(InputConnection connection, String separators) { - // getWordRangeAtCursor returns null if the connection is null - Range range = getWordRangeAtCursor(connection, separators); - if (range == null) return; - - connection.finishComposingText(); - // Move cursor to beginning of word, to avoid crash when cursor is outside - // of valid range after deleting text. - int newCursor = getCursorPosition(connection) - range.mCharsBefore; - connection.setSelection(newCursor, newCursor); - connection.deleteSurroundingText(0, range.mCharsBefore + range.mCharsAfter); - } - - /** * Represents a range of text, relative to the current cursor position. */ public static class Range { diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index cad69bb0e..8e8adc1c2 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -51,6 +51,7 @@ public class ExpandableDictionary extends Dictionary { private Object mUpdatingLock = new Object(); private static class Node { + Node() {} char mCode; int mFrequency; boolean mTerminal; @@ -300,7 +301,7 @@ public class ExpandableDictionary extends Dictionary { finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength); } if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, - DataType.UNIGRAM)) { + Dictionary.UNIGRAM)) { return; } } @@ -341,7 +342,7 @@ public class ExpandableDictionary extends Dictionary { snr * addedAttenuation, mInputLength); } callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, - DataType.UNIGRAM); + Dictionary.UNIGRAM); } } if (children != null) { @@ -505,7 +506,7 @@ public class ExpandableDictionary extends Dictionary { } while (node != null); callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId, - DataType.BIGRAM); + Dictionary.BIGRAM); } } @@ -547,6 +548,7 @@ public class ExpandableDictionary extends Dictionary { } private class LoadDictionaryTask extends Thread { + LoadDictionaryTask() {} @Override public void run() { loadDictionaryAsync(); diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java new file mode 100644 index 000000000..f7afed2a5 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2011 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.text.InputType; +import android.util.Log; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.compat.InputTypeCompatUtils; + +/** + * Class to hold attributes of the input field. + */ +public class InputAttributes { + private final String TAG = InputAttributes.class.getSimpleName(); + + final public boolean mInputTypeNoAutoCorrect; + final public boolean mIsSettingsSuggestionStripOn; + final public boolean mApplicationSpecifiedCompletionOn; + + public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) { + final int inputType = null != editorInfo ? editorInfo.inputType : 0; + final int inputClass = inputType & InputType.TYPE_MASK_CLASS; + if (inputClass != InputType.TYPE_CLASS_TEXT) { + // If we are not looking at a TYPE_CLASS_TEXT field, the following strange + // cases may arise, so we do a couple sanity checks for them. If it's a + // TYPE_CLASS_TEXT field, these special cases cannot happen, by construction + // of the flags. + if (null == editorInfo) { + Log.w(TAG, "No editor info for this field. Bug?"); + } else if (InputType.TYPE_NULL == inputType) { + // TODO: We should honor TYPE_NULL specification. + Log.i(TAG, "InputType.TYPE_NULL is specified"); + } else if (inputClass == 0) { + // TODO: is this check still necessary? + Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x" + + " imeOptions=0x%08x", + inputType, editorInfo.imeOptions)); + } + mIsSettingsSuggestionStripOn = false; + mInputTypeNoAutoCorrect = false; + mApplicationSpecifiedCompletionOn = false; + } else { + final int variation = inputType & InputType.TYPE_MASK_VARIATION; + final boolean flagNoSuggestions = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + final boolean flagMultiLine = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE); + final boolean flagAutoCorrect = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + final boolean flagAutoComplete = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); + + // Make sure that passwords are not displayed in {@link SuggestionsView}. + if (InputTypeCompatUtils.isPasswordInputType(inputType) + || InputTypeCompatUtils.isVisiblePasswordInputType(inputType) + || InputTypeCompatUtils.isEmailVariation(variation) + || InputType.TYPE_TEXT_VARIATION_URI == variation + || InputType.TYPE_TEXT_VARIATION_FILTER == variation + || flagNoSuggestions + || flagAutoComplete) { + mIsSettingsSuggestionStripOn = false; + } else { + mIsSettingsSuggestionStripOn = true; + } + + // If it's a browser edit field and auto correct is not ON explicitly, then + // disable auto correction, but keep suggestions on. + // If NO_SUGGESTIONS is set, don't do prediction. + // If it's not multiline and the autoCorrect flag is not set, then don't correct + if ((variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT + && !flagAutoCorrect) + || flagNoSuggestions + || (!flagAutoCorrect && !flagMultiLine)) { + mInputTypeNoAutoCorrect = true; + } else { + mInputTypeNoAutoCorrect = false; + } + + mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode; + } + } + + private void dumpFlags(final int inputType) { + Log.i(TAG, "Input class:"); + final int inputClass = inputType & InputType.TYPE_MASK_CLASS; + if (inputClass == InputType.TYPE_CLASS_TEXT) + Log.i(TAG, " TYPE_CLASS_TEXT"); + if (inputClass == InputType.TYPE_CLASS_PHONE) + Log.i(TAG, " TYPE_CLASS_PHONE"); + if (inputClass == InputType.TYPE_CLASS_NUMBER) + Log.i(TAG, " TYPE_CLASS_NUMBER"); + if (inputClass == InputType.TYPE_CLASS_DATETIME) + Log.i(TAG, " TYPE_CLASS_DATETIME"); + Log.i(TAG, "Variation:"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS)) + Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_ADDRESS"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT)) + Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_SUBJECT"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_FILTER)) + Log.i(TAG, " TYPE_TEXT_VARIATION_FILTER"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE)) + Log.i(TAG, " TYPE_TEXT_VARIATION_LONG_MESSAGE"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_NORMAL)) + Log.i(TAG, " TYPE_TEXT_VARIATION_NORMAL"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PASSWORD)) + Log.i(TAG, " TYPE_TEXT_VARIATION_PASSWORD"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PERSON_NAME)) + Log.i(TAG, " TYPE_TEXT_VARIATION_PERSON_NAME"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_PHONETIC)) + Log.i(TAG, " TYPE_TEXT_VARIATION_PHONETIC"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS)) + Log.i(TAG, " TYPE_TEXT_VARIATION_POSTAL_ADDRESS"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)) + Log.i(TAG, " TYPE_TEXT_VARIATION_SHORT_MESSAGE"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_URI)) + Log.i(TAG, " TYPE_TEXT_VARIATION_URI"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)) + Log.i(TAG, " TYPE_TEXT_VARIATION_VISIBLE_PASSWORD"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT)) + Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EDIT_TEXT"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS)) + Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS"); + if (0 != (inputType & InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD)) + Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_PASSWORD"); + Log.i(TAG, "Flags:"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS)) + Log.i(TAG, " TYPE_TEXT_FLAG_NO_SUGGESTIONS"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE)) + Log.i(TAG, " TYPE_TEXT_FLAG_MULTI_LINE"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE)) + Log.i(TAG, " TYPE_TEXT_FLAG_IME_MULTI_LINE"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS)) + Log.i(TAG, " TYPE_TEXT_FLAG_CAP_WORDS"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)) + Log.i(TAG, " TYPE_TEXT_FLAG_CAP_SENTENCES"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS)) + Log.i(TAG, " TYPE_TEXT_FLAG_CAP_CHARACTERS"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT)) + Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_CORRECT"); + if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE)) + Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_COMPLETE"); + } + + // Pretty print + @Override + public String toString() { + return "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect + + "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn + + "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn; + } +} diff --git a/java/src/com/android/inputmethod/latin/JniUtils.java b/java/src/com/android/inputmethod/latin/JniUtils.java new file mode 100644 index 000000000..4808b867a --- /dev/null +++ b/java/src/com/android/inputmethod/latin/JniUtils.java @@ -0,0 +1,41 @@ +/* + * 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.util.Log; + +import com.android.inputmethod.latin.define.JniLibName; + +public class JniUtils { + private static final String TAG = JniUtils.class.getSimpleName(); + + private JniUtils() { + // This utility class is not publicly instantiable. + } + + public static void loadNativeLibrary() { + try { + System.loadLibrary(JniLibName.JNI_LIB_NAME); + } catch (UnsatisfiedLinkError ule) { + Log.e(TAG, "Could not load native library " + JniLibName.JNI_LIB_NAME); + if (LatinImeLogger.sDBG) { + throw new RuntimeException( + "Could not load native library " + JniLibName.JNI_LIB_NAME); + } + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java new file mode 100644 index 000000000..bc0792434 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -0,0 +1,86 @@ +/* + * 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.text.TextUtils; + +import java.util.ArrayList; + +/** + * This class encapsulates data about a word previously composed, but that has been + * committed already. This is used for resuming suggestion, and cancel auto-correction. + */ +public class LastComposedWord { + // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with + // no hinting from the IME. It happens when some external event happens (rotating the device, + // for example) or when auto-correction is off by settings or editor attributes. + public static final int COMMIT_TYPE_USER_TYPED_WORD = 0; + // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip. + public static final int COMMIT_TYPE_MANUAL_PICK = 1; + // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best + // for the current user input. It may be different from what the user typed (true auto-correct) + // or it may be exactly what the user typed if it's in the dictionary or the IME does not have + // enough confidence in any suggestion to auto-correct (auto-correct to typed word). + public static final int COMMIT_TYPE_DECIDED_WORD = 2; + // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling + // an auto-correction. + public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3; + + public static final int NOT_A_SEPARATOR = -1; + + public final ArrayList<int[]> mCodes; + public final int[] mXCoordinates; + public final int[] mYCoordinates; + public final String mTypedWord; + public final String mCommittedWord; + public final int mSeparatorCode; + + private boolean mActive; + + public static final LastComposedWord NOT_A_COMPOSED_WORD = + new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR); + + // Warning: this is using the passed objects as is and fully expects them to be + // immutable. Do not fiddle with their contents after you passed them to this constructor. + public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates, + final int[] yCoordinates, final String typedWord, final String committedWord, + final int separatorCode) { + mCodes = codes; + mXCoordinates = xCoordinates; + mYCoordinates = yCoordinates; + mTypedWord = typedWord; + mCommittedWord = committedWord; + mSeparatorCode = separatorCode; + mActive = true; + } + + public void deactivate() { + mActive = false; + } + + public boolean canRevertCommit() { + return mActive && !TextUtils.isEmpty(mCommittedWord); + } + + public boolean didCommitTypedWord() { + return TextUtils.equals(mTypedWord, mCommittedWord); + } + + public static int getSeparatorLength(final int separatorCode) { + return NOT_A_SEPARATOR == separatorCode ? 0 : 1; + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 9c321bcb9..fa5a46fca 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -25,10 +25,12 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Rect; import android.inputmethodservice.InputMethodService; import android.media.AudioManager; import android.net.ConnectivityManager; import android.os.Debug; +import android.os.IBinder; import android.os.Message; import android.os.SystemClock; import android.preference.PreferenceActivity; @@ -38,10 +40,10 @@ import android.text.TextUtils; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; @@ -49,26 +51,29 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.InputConnection; import com.android.inputmethod.accessibility.AccessibilityUtils; +import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.compat.CompatUtils; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.compat.InputConnectionCompatUtils; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.SuggestionSpanUtils; -import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.LanguageSwitcherProxy; import com.android.inputmethod.deprecated.VoiceProxy; -import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.LatinKeyboard; import com.android.inputmethod.keyboard.LatinKeyboardView; +import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; /** @@ -77,7 +82,6 @@ import java.util.Locale; public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, SuggestionsView.Listener { private static final String TAG = LatinIME.class.getSimpleName(); - private static final boolean PERF_DEBUG = false; private static final boolean TRACE = false; private static boolean DEBUG; @@ -107,7 +111,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /** * The private IME option used to indicate that the given text field needs * ASCII code points input. + * + * @deprecated Use {@link EditorInfo#IME_FLAG_FORCE_ASCII}. */ + @SuppressWarnings("dep-ann") public static final String IME_OPTION_FORCE_ASCII = "forceAscii"; /** @@ -143,6 +150,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar */ private static final String SCHEME_PACKAGE = "package"; + // TODO: migrate this to SettingsValues private int mSuggestionVisibility; private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE = R.string.prefs_suggestion_visibility_show_value; @@ -157,51 +165,57 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar SUGGESTION_VISIBILILTY_HIDE_VALUE }; - private Settings.Values mSettingsValues; + private static final int SPACE_STATE_NONE = 0; + // Double space: the state where the user pressed space twice quickly, which LatinIME + // resolved as period-space. Undoing this converts the period to a space. + private static final int SPACE_STATE_DOUBLE = 1; + // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip + // have just been swapped. Undoing this swaps them back; the space is still considered weak. + private static final int SPACE_STATE_SWAP_PUNCTUATION = 2; + // Weak space: a space that should be swapped only by suggestion strip punctuation. Weak + // spaces happen when the user presses space, accepting the current suggestion (whether + // it's an auto-correction or not). + private static final int SPACE_STATE_WEAK = 3; + // Phantom space: a not-yet-inserted space that should get inserted on the next input, + // character provided it's not a separator. If it's a separator, the phantom space is dropped. + // Phantom spaces happen when a user chooses a word from the suggestion strip. + private static final int SPACE_STATE_PHANTOM = 4; + + // Current space state of the input method. This can be any of the above constants. + private int mSpaceState; + + private SettingsValues mSettingsValues; + private InputAttributes mInputAttributes; private View mExtractArea; private View mKeyPreviewBackingView; private View mSuggestionsContainer; private SuggestionsView mSuggestionsView; - private Suggest mSuggest; + /* package for tests */ Suggest mSuggest; private CompletionInfo[] mApplicationSpecifiedCompletions; private InputMethodManagerCompatWrapper mImm; private Resources mResources; private SharedPreferences mPrefs; - private String mInputMethodId; - private KeyboardSwitcher mKeyboardSwitcher; - private SubtypeSwitcher mSubtypeSwitcher; + private final KeyboardSwitcher mKeyboardSwitcher; + private final SubtypeSwitcher mSubtypeSwitcher; private VoiceProxy mVoiceProxy; + private boolean mShouldSwitchToLastSubtype = true; private UserDictionary mUserDictionary; private UserBigramDictionary mUserBigramDictionary; private UserUnigramDictionary mUserUnigramDictionary; - private boolean mIsUserDictionaryAvaliable; - - // TODO: Create an inner class to group options and pseudo-options to improve readability. - // These variables are initialized according to the {@link EditorInfo#inputType}. - private boolean mInsertSpaceOnPickSuggestionManually; - private boolean mInputTypeNoAutoCorrect; - private boolean mIsSettingsSuggestionStripOn; - private boolean mApplicationSpecifiedCompletionOn; + private boolean mIsUserDictionaryAvailable; - private final StringBuilder mComposingStringBuilder = new StringBuilder(); + private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; private WordComposer mWordComposer = new WordComposer(); - private CharSequence mBestWord; - private boolean mHasUncommittedTypedChars; - // Magic space: a space that should disappear on space/apostrophe insertion, move after the - // punctuation on punctuation insertion, and become a real space on alpha char insertion. - private boolean mJustAddedMagicSpace; // This indicates whether the last char is a magic space. - // This indicates whether the last keypress resulted in processing of double space replacement - // with period-space. - private boolean mJustReplacedDoubleSpace; private int mCorrectionMode; - private int mCommittedLength; + // Keep track of the last selection range to decide if we need to show word alternatives - private int mLastSelectionStart; - private int mLastSelectionEnd; + private static final int NOT_A_CURSOR_POSITION = -1; + private int mLastSelectionStart = NOT_A_CURSOR_POSITION; + private int mLastSelectionEnd = NOT_A_CURSOR_POSITION; // Whether we are expecting an onUpdateSelection event to fire. If it does when we don't // "expect" it, it means the user actually moved the cursor. @@ -209,15 +223,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private int mDeleteCount; private long mLastKeyTime; - private AudioManager mAudioManager; - private float mFxVolume = -1.0f; // default volume - private boolean mSilentModeOn; // System-wide current configuration - - private VibratorCompatWrapper mVibrator; - private long mKeypressVibrationDuration = -1; - - // TODO: Move this flag to VoiceProxy - private boolean mConfigurationChanging; + private AudioAndHapticFeedbackManager mFeedbackManager; // Member variables for remembering the current device orientation. private int mDisplayOrientation; @@ -229,29 +235,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Keeps track of most recently inserted text (multi-character key) for reverting private CharSequence mEnteredText; - private final ComposingStateManager mComposingStateManager = - ComposingStateManager.getInstance(); + private boolean mIsAutoCorrectionIndicatorOn; public final UIHandler mHandler = new UIHandler(this); public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> { - private static final int MSG_UPDATE_SUGGESTIONS = 0; private static final int MSG_UPDATE_SHIFT_STATE = 1; private static final int MSG_VOICE_RESULTS = 2; - private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 3; - private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 4; - private static final int MSG_SPACE_TYPED = 5; - private static final int MSG_KEY_TYPED = 6; - private static final int MSG_SET_BIGRAM_PREDICTIONS = 7; - private static final int MSG_PENDING_IMS_CALLBACK = 8; - - private int mDelayBeforeFadeoutLanguageOnSpacebar; + private static final int MSG_SPACE_TYPED = 4; + private static final int MSG_SET_BIGRAM_PREDICTIONS = 5; + private static final int MSG_PENDING_IMS_CALLBACK = 6; + private static final int MSG_UPDATE_SUGGESTIONS = 7; + private int mDelayUpdateSuggestions; private int mDelayUpdateShiftState; - private int mDurationOfFadeoutLanguageOnSpacebar; - private float mFinalFadeoutFactorOfLanguageOnSpacebar; private long mDoubleSpacesTurnIntoPeriodTimeout; - private long mIgnoreSpecialKeyTimeout; public UIHandler(LatinIME outerInstance) { super(outerInstance); @@ -259,27 +257,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public void onCreate() { final Resources res = getOuterInstance().getResources(); - mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger( - R.integer.config_delay_before_fadeout_language_on_spacebar); mDelayUpdateSuggestions = res.getInteger(R.integer.config_delay_update_suggestions); mDelayUpdateShiftState = res.getInteger(R.integer.config_delay_update_shift_state); - mDurationOfFadeoutLanguageOnSpacebar = res.getInteger( - R.integer.config_duration_of_fadeout_language_on_spacebar); - mFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( - R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; mDoubleSpacesTurnIntoPeriodTimeout = res.getInteger( R.integer.config_double_spaces_turn_into_period_timeout); - mIgnoreSpecialKeyTimeout = res.getInteger( - R.integer.config_ignore_special_key_timeout); } @Override public void handleMessage(Message msg) { final LatinIME latinIme = getOuterInstance(); final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher; - final LatinKeyboardView inputView = switcher.getKeyboardView(); switch (msg.what) { case MSG_UPDATE_SUGGESTIONS: latinIme.updateSuggestions(); @@ -291,23 +280,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar latinIme.updateBigramPredictions(); break; case MSG_VOICE_RESULTS: + final Keyboard keyboard = switcher.getKeyboard(); latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization() - || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); - break; - case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR: - if (inputView != null) { - inputView.setSpacebarTextFadeFactor( - (1.0f + mFinalFadeoutFactorOfLanguageOnSpacebar) / 2, - (LatinKeyboard)msg.obj); - } - sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj), - mDurationOfFadeoutLanguageOnSpacebar); - break; - case MSG_DISMISS_LANGUAGE_ON_SPACEBAR: - if (inputView != null) { - inputView.setSpacebarTextFadeFactor(mFinalFadeoutFactorOfLanguageOnSpacebar, - (LatinKeyboard)msg.obj); - } + || (keyboard != null && keyboard.isShiftedOrShiftLocked())); break; } } @@ -325,7 +300,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return hasMessages(MSG_UPDATE_SUGGESTIONS); } - public void postUpdateShiftKeyState() { + public void postUpdateShiftState() { removeMessages(MSG_UPDATE_SHIFT_STATE); sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE), mDelayUpdateShiftState); } @@ -347,30 +322,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar sendMessage(obtainMessage(MSG_VOICE_RESULTS)); } - public void startDisplayLanguageOnSpacebar(boolean localeChanged) { - final LatinIME latinIme = getOuterInstance(); - removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR); - removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR); - final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView(); - if (inputView != null) { - final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard(); - // The language is always displayed when the delay is negative. - final boolean needsToDisplayLanguage = localeChanged - || mDelayBeforeFadeoutLanguageOnSpacebar < 0; - // The language is never displayed when the delay is zero. - if (mDelayBeforeFadeoutLanguageOnSpacebar != 0) { - inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f - : mFinalFadeoutFactorOfLanguageOnSpacebar, - keyboard); - } - // The fadeout animation will start when the delay is positive. - if (localeChanged && mDelayBeforeFadeoutLanguageOnSpacebar > 0) { - sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), - mDelayBeforeFadeoutLanguageOnSpacebar); - } - } - } - public void startDoubleSpacesTimer() { removeMessages(MSG_SPACE_TYPED); sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED), mDoubleSpacesTurnIntoPeriodTimeout); @@ -384,21 +335,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return hasMessages(MSG_SPACE_TYPED); } - public void startKeyTypedTimer() { - removeMessages(MSG_KEY_TYPED); - sendMessageDelayed(obtainMessage(MSG_KEY_TYPED), mIgnoreSpecialKeyTimeout); - } - - public boolean isIgnoringSpecialKey() { - return hasMessages(MSG_KEY_TYPED); - } - // Working variables for the following methods. private boolean mIsOrientationChanging; - private boolean mPendingSuccesiveImsCallback; + private boolean mPendingSuccessiveImsCallback; private boolean mHasPendingStartInput; private boolean mHasPendingFinishInputView; private boolean mHasPendingFinishInput; + private EditorInfo mAppliedEditorInfo; public void startOrientationChanging() { removeMessages(MSG_PENDING_IMS_CALLBACK); @@ -416,18 +359,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHasPendingStartInput = false; } - private void executePendingImsCallback(LatinIME latinIme, EditorInfo attribute, + private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo, boolean restarting) { if (mHasPendingFinishInputView) latinIme.onFinishInputViewInternal(mHasPendingFinishInput); if (mHasPendingFinishInput) latinIme.onFinishInputInternal(); if (mHasPendingStartInput) - latinIme.onStartInputInternal(attribute, restarting); + latinIme.onStartInputInternal(editorInfo, restarting); resetPendingImsCallback(); } - public void onStartInput(EditorInfo attribute, boolean restarting) { + public void onStartInput(EditorInfo editorInfo, boolean restarting) { if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { // Typically this is the second onStartInput after orientation changed. mHasPendingStartInput = true; @@ -435,30 +378,32 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mIsOrientationChanging && restarting) { // This is the first onStartInput after orientation changed. mIsOrientationChanging = false; - mPendingSuccesiveImsCallback = true; + mPendingSuccessiveImsCallback = true; } final LatinIME latinIme = getOuterInstance(); - executePendingImsCallback(latinIme, attribute, restarting); - latinIme.onStartInputInternal(attribute, restarting); + executePendingImsCallback(latinIme, editorInfo, restarting); + latinIme.onStartInputInternal(editorInfo, restarting); } } - public void onStartInputView(EditorInfo attribute, boolean restarting) { - if (hasMessages(MSG_PENDING_IMS_CALLBACK)) { - // Typically this is the second onStartInputView after orientation changed. - resetPendingImsCallback(); - } else { - if (mPendingSuccesiveImsCallback) { - // This is the first onStartInputView after orientation changed. - mPendingSuccesiveImsCallback = false; - resetPendingImsCallback(); - sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), - PENDING_IMS_CALLBACK_DURATION); - } - final LatinIME latinIme = getOuterInstance(); - executePendingImsCallback(latinIme, attribute, restarting); - latinIme.onStartInputViewInternal(attribute, restarting); - } + public void onStartInputView(EditorInfo editorInfo, boolean restarting) { + if (hasMessages(MSG_PENDING_IMS_CALLBACK) + && KeyboardId.equivalentEditorInfoForKeyboard(editorInfo, mAppliedEditorInfo)) { + // Typically this is the second onStartInputView after orientation changed. + resetPendingImsCallback(); + } else { + if (mPendingSuccessiveImsCallback) { + // This is the first onStartInputView after orientation changed. + mPendingSuccessiveImsCallback = false; + resetPendingImsCallback(); + sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK), + PENDING_IMS_CALLBACK_DURATION); + } + final LatinIME latinIme = getOuterInstance(); + executePendingImsCallback(latinIme, editorInfo, restarting); + latinIme.onStartInputViewInternal(editorInfo, restarting); + mAppliedEditorInfo = editorInfo; + } } public void onFinishInputView(boolean finishingInput) { @@ -468,6 +413,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { final LatinIME latinIme = getOuterInstance(); latinIme.onFinishInputViewInternal(finishingInput); + mAppliedEditorInfo = null; } } @@ -483,6 +429,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + public LatinIME() { + super(); + mSubtypeSwitcher = SubtypeSwitcher.getInstance(); + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + } + @Override public void onCreate() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -492,15 +444,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar InputMethodManagerCompatWrapper.init(this); SubtypeSwitcher.init(this); KeyboardSwitcher.init(this, prefs); - AccessibilityUtils.init(this, prefs); + AccessibilityUtils.init(this); super.onCreate(); mImm = InputMethodManagerCompatWrapper.getInstance(); - mInputMethodId = Utils.getInputMethodId(mImm, getPackageName()); - mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - mKeyboardSwitcher = KeyboardSwitcher.getInstance(); - mVibrator = VibratorCompatWrapper.getInstance(this); mHandler.onCreate(); DEBUG = LatinImeLogger.sDBG; @@ -509,6 +457,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar loadSettings(); + // TODO: remove the following when it's not needed by updateCorrectionMode() any more + mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); + updateCorrectionMode(); + Utils.GCUtils.getInstance().reset(); boolean tryGC = true; for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { @@ -525,8 +477,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Register to receive ringer mode change and network state change. // Also receive installation and removal of a dictionary pack. final IntentFilter filter = new IntentFilter(); - filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); registerReceiver(mReceiver, filter); mVoiceProxy = VoiceProxy.init(this, prefs, mHandler); @@ -545,11 +497,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Has to be package-visible for unit tests /* package */ void loadSettings() { if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - mSettingsValues = new Settings.Values(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); + mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); + mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); - updateSoundEffectVolume(); - updateKeypressVibrationDuration(); } private void initSuggest() { @@ -566,7 +516,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar oldContactsDictionary = null; } - int mainDicResId = Utils.getMainDictionaryResourceId(res); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); mSuggest = new Suggest(this, mainDicResId, keyboardLocale); if (mSettingsValues.mAutoCorrectEnabled) { mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); @@ -574,7 +524,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mUserDictionary = new UserDictionary(this, localeStr); mSuggest.setUserDictionary(mUserDictionary); - mIsUserDictionaryAvaliable = mUserDictionary.isEnabled(); + mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); resetContactsDictionary(oldContactsDictionary); @@ -586,8 +536,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); mSuggest.setUserBigramDictionary(mUserBigramDictionary); - updateCorrectionMode(); - LocaleUtils.setSystemLocale(res, savedLocale); } @@ -626,7 +574,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar /* package private */ void resetSuggestMainDict() { final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); - int mainDicResId = Utils.getMainDictionaryResourceId(mResources); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); } @@ -647,22 +595,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void onConfigurationChanged(Configuration conf) { mSubtypeSwitcher.onConfigurationChanged(conf); - mComposingStateManager.onFinishComposingText(); // If orientation changed while predicting, commit the change if (mDisplayOrientation != conf.orientation) { mDisplayOrientation = conf.orientation; mHandler.startOrientationChanging(); final InputConnection ic = getCurrentInputConnection(); - commitTyped(ic); + commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); if (ic != null) ic.finishComposingText(); // For voice input if (isShowingOptionDialog()) mOptionsDialog.dismiss(); } - mConfigurationChanging = true; + mVoiceProxy.startChangingConfiguration(); super.onConfigurationChanged(conf); mVoiceProxy.onConfigurationChanged(conf); - mConfigurationChanging = false; + mVoiceProxy.finishChangingConfiguration(); // This will work only when the subtype is not supported. LanguageSwitcherProxy.onConfigurationChanged(conf); @@ -695,13 +642,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } @Override - public void onStartInput(EditorInfo attribute, boolean restarting) { - mHandler.onStartInput(attribute, restarting); + public void onStartInput(EditorInfo editorInfo, boolean restarting) { + mHandler.onStartInput(editorInfo, restarting); } @Override - public void onStartInputView(EditorInfo attribute, boolean restarting) { - mHandler.onStartInputView(attribute, restarting); + public void onStartInputView(EditorInfo editorInfo, boolean restarting) { + mHandler.onStartInputView(editorInfo, restarting); } @Override @@ -714,20 +661,39 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.onFinishInput(); } - private void onStartInputInternal(EditorInfo attribute, boolean restarting) { - super.onStartInput(attribute, restarting); + private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { + super.onStartInput(editorInfo, restarting); } - private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) { - super.onStartInputView(attribute, restarting); + private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) { + super.onStartInputView(editorInfo, restarting); final KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getKeyboardView(); + if (editorInfo == null) { + Log.e(TAG, "Null EditorInfo in onStartInputView()"); + if (LatinImeLogger.sDBG) { + throw new NullPointerException("Null EditorInfo in onStartInputView()"); + } + return; + } if (DEBUG) { - Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none" - : String.format("inputType=0x%08x imeOptions=0x%08x", - attribute.inputType, attribute.imeOptions))); + Log.d(TAG, "onStartInputView: editorInfo:" + + String.format("inputType=0x%08x imeOptions=0x%08x", + editorInfo.inputType, editorInfo.imeOptions)); + } + if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { + Log.w(TAG, "Deprecated private IME option specified: " + + editorInfo.privateImeOptions); + Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead"); + } + if (StringUtils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { + Log.w(TAG, "Deprecated private IME option specified: " + + editorInfo.privateImeOptions); + Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); } + + LatinImeLogger.onStartInputView(editorInfo); // In landscape mode, this method gets called without the input view being created. if (inputView == null) { return; @@ -736,47 +702,45 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Forward this event to the accessibility utilities, if enabled. final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance(); if (accessUtils.isTouchExplorationEnabled()) { - accessUtils.onStartInputViewInternal(attribute, restarting); + accessUtils.onStartInputViewInternal(editorInfo, restarting); } mSubtypeSwitcher.updateParametersOnStartInputView(); - TextEntryState.reset(); - // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to // know now whether this is a password text field, because we need to know now whether we // want to enable the voice button. - final VoiceProxy voiceIme = mVoiceProxy; - final int inputType = (attribute != null) ? attribute.inputType : 0; - voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) + final int inputType = editorInfo.inputType; + mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); // The EditorInfo might have a flag that affects fullscreen mode. // Note: This call should be done by InputMethodService? updateFullscreenMode(); - initializeInputAttributes(attribute); + mLastSelectionStart = editorInfo.initialSelStart; + mLastSelectionEnd = editorInfo.initialSelEnd; + mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); + mApplicationSpecifiedCompletions = null; inputView.closing(); mEnteredText = null; - mComposingStringBuilder.setLength(0); - mHasUncommittedTypedChars = false; + resetComposingState(true /* alsoResetLastComposedWord */); mDeleteCount = 0; - mJustAddedMagicSpace = false; - mJustReplacedDoubleSpace = false; + mSpaceState = SPACE_STATE_NONE; loadSettings(); updateCorrectionMode(); - updateSuggestionVisibility(mPrefs, mResources); + updateSuggestionVisibility(mResources); if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) { mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); } - mVoiceProxy.loadSettings(attribute, mPrefs); + mVoiceProxy.loadSettings(editorInfo, mPrefs); // This will work only when the subtype is not supported. LanguageSwitcherProxy.loadSettings(); if (mSubtypeSwitcher.isKeyboardMode()) { - switcher.loadKeyboard(attribute, mSettingsValues); + switcher.loadKeyboard(editorInfo, mSettingsValues); } if (mSuggestionsView != null) @@ -785,83 +749,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar isSuggestionsStripVisible(), /* needsInputViewShown */ false); // Delay updating suggestions because keyboard input view may not be shown at this point. mHandler.postUpdateSuggestions(); + mHandler.cancelDoubleSpacesTimer(); inputView.setKeyPreviewPopupEnabled(mSettingsValues.mKeyPreviewPopupOn, mSettingsValues.mKeyPreviewPopupDismissDelay); inputView.setProximityCorrectionEnabled(true); - voiceIme.onStartInputView(inputView.getWindowToken()); + mVoiceProxy.onStartInputView(inputView.getWindowToken()); if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } - private void initializeInputAttributes(EditorInfo attribute) { - if (attribute == null) - return; - final int inputType = attribute.inputType; - if (inputType == InputType.TYPE_NULL) { - // TODO: We should honor TYPE_NULL specification. - Log.i(TAG, "InputType.TYPE_NULL is specified"); - } - final int inputClass = inputType & InputType.TYPE_MASK_CLASS; - final int variation = inputType & InputType.TYPE_MASK_VARIATION; - if (inputClass == 0) { - Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x imeOptions=0x%08x", - inputType, attribute.imeOptions)); - } - - mInsertSpaceOnPickSuggestionManually = false; - mInputTypeNoAutoCorrect = false; - mIsSettingsSuggestionStripOn = false; - mApplicationSpecifiedCompletionOn = false; - mApplicationSpecifiedCompletions = null; - - if (inputClass == InputType.TYPE_CLASS_TEXT) { - mIsSettingsSuggestionStripOn = true; - // Make sure that passwords are not displayed in {@link SuggestionsView}. - if (InputTypeCompatUtils.isPasswordInputType(inputType) - || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)) { - mIsSettingsSuggestionStripOn = false; - } - if (InputTypeCompatUtils.isEmailVariation(variation) - || variation == InputType.TYPE_TEXT_VARIATION_PERSON_NAME) { - // The point in turning this off is that we don't want to insert a space after - // a name when filling a form: we can't delete trailing spaces when changing fields - mInsertSpaceOnPickSuggestionManually = false; - } else { - mInsertSpaceOnPickSuggestionManually = true; - } - if (InputTypeCompatUtils.isEmailVariation(variation)) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { - mIsSettingsSuggestionStripOn = false; - } else if (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { - // If it's a browser edit field and auto correct is not ON explicitly, then - // disable auto correction, but keep suggestions on. - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { - mInputTypeNoAutoCorrect = true; - } - } - - // If NO_SUGGESTIONS is set, don't do prediction. - if ((inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { - mIsSettingsSuggestionStripOn = false; - mInputTypeNoAutoCorrect = true; - } - // If it's not multiline and the autoCorrect flag is not set, then don't correct - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 - && (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { - mInputTypeNoAutoCorrect = true; - } - if ((inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { - mIsSettingsSuggestionStripOn = false; - mApplicationSpecifiedCompletionOn = isFullscreenMode(); - } - } - } - @Override public void onWindowHidden() { super.onWindowHidden(); @@ -874,7 +772,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.commit(); - mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); + mVoiceProxy.flushVoiceInputLogs(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); @@ -900,9 +798,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, - int candidatesStart, int candidatesEnd) { + int composingSpanStart, int composingSpanEnd) { super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, - candidatesStart, candidatesEnd); + composingSpanStart, composingSpanEnd); if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart @@ -911,51 +809,58 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar + ", lse=" + mLastSelectionEnd + ", nss=" + newSelStart + ", nse=" + newSelEnd - + ", cs=" + candidatesStart - + ", ce=" + candidatesEnd); + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd); } mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart); - // If the current selection in the text view changes, we should - // clear whatever candidate text we have. - final boolean selectionChanged = (newSelStart != candidatesEnd - || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart; - final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1; + // TODO: refactor the following code to be less contrived. + // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means + // that the cursor is not at the end of the composing span, or there is a selection. + // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place + // as last time we were called (if there is a selection, it means the start hasn't + // changed, so it's the end that did). + final boolean selectionChanged = (newSelStart != composingSpanEnd + || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart; + // if composingSpanStart and composingSpanEnd are -1, it means there is no composing + // span in the view - we can use that to narrow down whether the cursor was moved + // by us or not. If we are composing a word but there is no composing span, then + // we know for sure the cursor moved while we were composing and we should reset + // the state. + final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1; if (!mExpectingUpdateSelection) { - if (((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars) - || mVoiceProxy.isVoiceInputHighlighted()) - && (selectionChanged || candidatesCleared)) { - mComposingStringBuilder.setLength(0); - mHasUncommittedTypedChars = false; - TextEntryState.reset(); - updateSuggestions(); - final InputConnection ic = getCurrentInputConnection(); - if (ic != null) { - ic.finishComposingText(); - } - mComposingStateManager.onFinishComposingText(); - mVoiceProxy.setVoiceInputHighlighted(false); - } else if (!mHasUncommittedTypedChars) { - TextEntryState.reset(); - updateSuggestions(); + // TAKE CARE: there is a race condition when we enter this test even when the user + // did not explicitly move the cursor. This happens when typing fast, where two keys + // turn this flag on in succession and both onUpdateSelection() calls arrive after + // the second one - the first call successfully avoids this test, but the second one + // enters. For the moment we rely on noComposingSpan to further reduce the impact. + + // TODO: the following is probably better done in resetEntireInputState(). + // it should only happen when the cursor moved, and the very purpose of the + // test below is to narrow down whether this happened or not. Likewise with + // the call to postUpdateShiftState. + // We set this to NONE because after a cursor move, we don't want the space + // state-related special processing to kick in. + mSpaceState = SPACE_STATE_NONE; + + if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) { + resetEntireInputState(); } - mJustAddedMagicSpace = false; // The user moved the cursor. - mJustReplacedDoubleSpace = false; + + mHandler.postUpdateShiftState(); } mExpectingUpdateSelection = false; - mHandler.postUpdateShiftKeyState(); + // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not + // here. It would probably be too expensive to call directly here but we may want to post a + // message to delay it. The point would be to unify behavior between backspace to the + // end of a word and manually put the pointer at the end of the word. // Make a note of the cursor position mLastSelectionStart = newSelStart; mLastSelectionEnd = newSelEnd; } - public void setLastSelection(int start, int end) { - mLastSelectionStart = start; - mLastSelectionEnd = end; - } - /** * This is called when the user has clicked on the extracted text view, * when running in fullscreen mode. The default implementation hides @@ -997,7 +902,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); mOptionsDialog = null; } - mVoiceProxy.hideVoiceWindow(mConfigurationChanging); + mVoiceProxy.hideVoiceWindow(); super.hideWindow(); } @@ -1011,20 +916,30 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } } - if (mApplicationSpecifiedCompletionOn) { + if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { clearSuggestions(); return; } - SuggestedWords.Builder builder = new SuggestedWords.Builder() - .setApplicationSpecifiedCompletions(applicationSpecifiedCompletions) - .setTypedWordValid(false) - .setHasMinimalSuggestion(false); + final List<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords = + SuggestedWords.getFromApplicationSpecifiedCompletions( + applicationSpecifiedCompletions); + final SuggestedWords suggestedWords = new SuggestedWords( + applicationSuggestedWords, + false /* typedWordValid */, + false /* hasAutoCorrectionCandidate */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */, + false /* isObsoleteSuggestions */); // When in fullscreen mode, show completions generated by the application - setSuggestions(builder.build()); - mBestWord = null; + final boolean isAutoCorrection = false; + setSuggestions(suggestedWords, isAutoCorrection); + setAutoCorrectionIndicator(isAutoCorrection); + // TODO: is this the right thing to do? What should we auto-correct to in + // this case? This says to keep whatever the user typed. + mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); setSuggestionStripShown(true); } } @@ -1032,8 +947,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private void setSuggestionStripShownInternal(boolean shown, boolean needsInputViewShown) { // TODO: Modify this if we support suggestions with hard keyboard if (onEvaluateInputViewShown() && mSuggestionsContainer != null) { + final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); + final boolean inputViewShown = (keyboardView != null) ? keyboardView.isShown() : false; final boolean shouldShowSuggestions = shown - && (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true); + && (needsInputViewShown ? inputViewShown : true); if (isFullscreenMode()) { mSuggestionsContainer.setVisibility( shouldShowSuggestions ? View.VISIBLE : View.GONE); @@ -1048,12 +965,34 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); } + private void adjustInputViewHeight() { + if (mKeyPreviewBackingView.getHeight() > 0) { + return; + } + + final KeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); + if (keyboardView == null) return; + final int keyboardHeight = keyboardView.getHeight(); + final int suggestionsHeight = mSuggestionsContainer.getHeight(); + final int displayHeight = mResources.getDisplayMetrics().heightPixels; + final Rect rect = new Rect(); + mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect); + final int notificationBarHeight = rect.top; + final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight + - keyboardHeight; + + final LayoutParams params = mKeyPreviewBackingView.getLayoutParams(); + params.height = mSuggestionsView.setMoreSuggestionsHeight(remainingHeight); + mKeyPreviewBackingView.setLayoutParams(params); + } + @Override public void onComputeInsets(InputMethodService.Insets outInsets) { super.onComputeInsets(outInsets); final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView == null || mSuggestionsContainer == null) return; + adjustInputViewHeight(); // In fullscreen mode, the height of the extract area managed by InputMethodService should // be considered. // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. @@ -1065,7 +1004,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final int extraHeight = extractHeight + backingHeight + suggestionsHeight; int touchY = extraHeight; // Need to set touchable region only if input view is being shown - if (mKeyboardSwitcher.isInputViewShown()) { + final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); + if (keyboardView != null && keyboardView.isShown()) { if (mSuggestionsContainer.getVisibility() == View.VISIBLE) { touchY -= suggestionsHeight; } @@ -1085,8 +1025,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar @Override public boolean onEvaluateFullscreenMode() { - return super.onEvaluateFullscreenMode() - && mResources.getBoolean(R.bool.config_use_fullscreen_mode); + // Reread resource value here, because this method is called by framework anytime as needed. + final boolean isFullscreenModeAllowed = + mSettingsValues.isFullscreenModeAllowed(getResources()); + return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed; } @Override @@ -1124,9 +1066,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_RIGHT: + final LatinKeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); + final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); // Enable shift key and DPAD to do selections - if (mKeyboardSwitcher.isInputViewShown() - && mKeyboardSwitcher.isShiftedOrShiftLocked()) { + if ((keyboardView != null && keyboardView.isShown()) + && (keyboard != null && keyboard.isShiftedOrShiftLocked())) { KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), event.getKeyCode(), event.getRepeatCount(), event.getDeviceId(), event.getScanCode(), @@ -1141,16 +1085,36 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return super.onKeyUp(keyCode, event); } - public void commitTyped(final InputConnection ic) { - if (!mHasUncommittedTypedChars) return; - mHasUncommittedTypedChars = false; - if (mComposingStringBuilder.length() > 0) { + // This will reset the whole input state to the starting state. It will clear + // the composing word, reset the last composed word, tell the inputconnection + // and the composingStateManager about it. + private void resetEntireInputState() { + resetComposingState(true /* alsoResetLastComposedWord */); + updateSuggestions(); + final InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ic.finishComposingText(); + } + mVoiceProxy.setVoiceInputHighlighted(false); + } + + private void resetComposingState(final boolean alsoResetLastComposedWord) { + mWordComposer.reset(); + if (alsoResetLastComposedWord) + mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; + } + + public void commitTyped(final InputConnection ic, final int separatorCode) { + if (!mWordComposer.isComposingWord()) return; + final CharSequence typedWord = mWordComposer.getTypedWord(); + if (typedWord.length() > 0) { + mLastComposedWord = mWordComposer.commitWord( + LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(), + separatorCode); if (ic != null) { - ic.commitText(mComposingStringBuilder, 1); + ic.commitText(typedWord, 1); } - mCommittedLength = mComposingStringBuilder.length(); - TextEntryState.acceptedTyped(mComposingStringBuilder); - addToUserUnigramAndBigramDictionaries(mComposingStringBuilder, + addToUserUnigramAndBigramDictionaries(typedWord, UserUnigramDictionary.FREQUENCY_FOR_TYPED); } updateSuggestions(); @@ -1166,60 +1130,41 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return false; } - private void swapSwapperAndSpace() { - final InputConnection ic = getCurrentInputConnection(); - if (ic == null) return; + // "ic" may be null + private void swapSwapperAndSpaceWhileInBatchEdit(final InputConnection ic) { + if (null == ic) return; CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called. if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Keyboard.CODE_SPACE) { - ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); ic.commitText(lastTwo.charAt(1) + " ", 1); - ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); } } - private void maybeDoubleSpace() { - if (mCorrectionMode == Suggest.CORRECTION_NONE) return; - final InputConnection ic = getCurrentInputConnection(); - if (ic == null) return; + private boolean maybeDoubleSpaceWhileInBatchEdit(final InputConnection ic) { + if (mCorrectionMode == Suggest.CORRECTION_NONE) return false; + if (ic == null) return false; final CharSequence lastThree = ic.getTextBeforeCursor(3, 0); if (lastThree != null && lastThree.length() == 3 - && Utils.canBeFollowedByPeriod(lastThree.charAt(0)) + && StringUtils.canBeFollowedByPeriod(lastThree.charAt(0)) && lastThree.charAt(1) == Keyboard.CODE_SPACE && lastThree.charAt(2) == Keyboard.CODE_SPACE && mHandler.isAcceptingDoubleSpaces()) { mHandler.cancelDoubleSpacesTimer(); - ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); ic.commitText(". ", 1); - ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); - mJustReplacedDoubleSpace = true; - } else { - mHandler.startDoubleSpacesTimer(); - } - } - - // "ic" must not null - private void maybeRemovePreviousPeriod(final InputConnection ic, CharSequence text) { - // When the text's first character is '.', remove the previous period - // if there is one. - CharSequence lastOne = ic.getTextBeforeCursor(1, 0); - if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == Keyboard.CODE_PERIOD - && text.charAt(0) == Keyboard.CODE_PERIOD) { - ic.deleteSurroundingText(1, 0); + return true; } + return false; } - private void removeTrailingSpace() { - final InputConnection ic = getCurrentInputConnection(); + // "ic" may be null + private static void removeTrailingSpaceWhileInBatchEdit(final InputConnection ic) { if (ic == null) return; - - CharSequence lastOne = ic.getTextBeforeCursor(1, 0); + final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); if (lastOne != null && lastOne.length() == 1 && lastOne.charAt(0) == Keyboard.CODE_SPACE) { ic.deleteSurroundingText(1, 0); @@ -1235,19 +1180,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return true; } - private boolean isAlphabet(int code) { - if (Character.isLetter(code)) { - return true; - } else { - return false; - } + private static boolean isAlphabet(int code) { + return Character.isLetter(code); } private void onSettingsKeyPressed() { if (isShowingOptionDialog()) return; if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { showSubtypeSelectorAndSettings(); - } else if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, false /* exclude aux subtypes */)) { + } else if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes( + false /* exclude aux subtypes */)) { showOptionsMenu(); } else { launchSettings(); @@ -1256,17 +1198,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // 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) { if (isShowingOptionDialog()) return false; switch (requestCode) { case CODE_SHOW_INPUT_METHOD_PICKER: - if (Utils.hasMultipleEnabledIMEsOrSubtypes(mImm, true /* include aux subtypes */)) { + if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { mImm.showInputMethodPicker(); return true; } return false; + case CODE_HAPTIC_AND_AUDIO_FEEDBACK: + hapticAndAudioFeedback(Keyboard.CODE_UNSPECIFIED); + return true; } return false; } @@ -1275,91 +1221,121 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return mOptionsDialog != null && mOptionsDialog.isShowing(); } + private static int getActionId(Keyboard keyboard) { + return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE; + } + + private void performeEditorAction(int actionId) { + final InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ic.performEditorAction(actionId); + } + } + + private void handleLanguageSwitchKey() { + final boolean includesOtherImes = mSettingsValues.mIncludesOtherImesInLanguageSwitchList; + final IBinder token = getWindow().getWindow().getAttributes().token; + if (mShouldSwitchToLastSubtype) { + final InputMethodSubtypeCompatWrapper lastSubtype = mImm.getLastInputMethodSubtype(); + final boolean lastSubtypeBelongsToThisIme = SubtypeUtils.checkIfSubtypeBelongsToThisIme( + this, lastSubtype); + if ((includesOtherImes || lastSubtypeBelongsToThisIme) + && mImm.switchToLastInputMethod(token)) { + mShouldSwitchToLastSubtype = false; + } else { + mImm.switchToNextInputMethod(token, !includesOtherImes); + mShouldSwitchToLastSubtype = true; + } + } else { + mImm.switchToNextInputMethod(token, !includesOtherImes); + } + } + + private void sendKeyCodePoint(int code) { + // TODO: Remove this special handling of digit letters. + // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}. + if (code >= '0' && code <= '9') { + super.sendKeyChar((char)code); + return; + } + + final InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + final String text = new String(new int[] { code }, 0, 1); + ic.commitText(text, text.length()); + } + } + // Implementation of {@link KeyboardActionListener}. @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final long when = SystemClock.uptimeMillis(); if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { mDeleteCount = 0; } mLastKeyTime = when; final KeyboardSwitcher switcher = mKeyboardSwitcher; - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - final boolean lastStateOfJustReplacedDoubleSpace = mJustReplacedDoubleSpace; - mJustReplacedDoubleSpace = false; - boolean shouldStartKeyTypedTimer = true; + // The space state depends only on the last character pressed and its own previous + // state. Here, we revert the space state to neutral if the key is actually modifying + // the input contents (any non-shift key), which is what we should do for + // all inputs that do not result in a special state. Each character handling is then + // free to override the state as they see fit. + final int spaceState = mSpaceState; + if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false; + + // TODO: Consolidate the double space timer, mLastKeyTime, and the space state. + if (primaryCode != Keyboard.CODE_SPACE) { + mHandler.cancelDoubleSpacesTimer(); + } + + boolean didAutoCorrect = false; switch (primaryCode) { case Keyboard.CODE_DELETE: - handleBackspace(lastStateOfJustReplacedDoubleSpace); + mSpaceState = SPACE_STATE_NONE; + handleBackspace(spaceState); mDeleteCount++; mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; LatinImeLogger.logOnDelete(); break; case Keyboard.CODE_SHIFT: - // Shift key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) { - switcher.toggleShift(); - } - shouldStartKeyTypedTimer = false; - break; case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: - // Symbol key is handled in onPress() when device has distinct multi-touch panel. - if (!distinctMultiTouch) { - switcher.changeKeyboardMode(); - } - shouldStartKeyTypedTimer = false; - break; - case Keyboard.CODE_CANCEL: - if (!isShowingOptionDialog()) { - handleClose(); - } + // Shift and symbol key is handled in onPressKey() and onReleaseKey(). break; case Keyboard.CODE_SETTINGS: - if (!mHandler.isIgnoringSpecialKey()) { - onSettingsKeyPressed(); - } - shouldStartKeyTypedTimer = false; - break; - case Keyboard.CODE_CAPSLOCK: - switcher.toggleCapsLock(); - //$FALL-THROUGH$ - case Keyboard.CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY: - // Dummy code for haptic and audio feedbacks. - vibrate(); - playKeyClick(primaryCode); + onSettingsKeyPressed(); break; case Keyboard.CODE_SHORTCUT: - if (!mHandler.isIgnoringSpecialKey()) { - mSubtypeSwitcher.switchToShortcutIME(); - } - shouldStartKeyTypedTimer = false; + mSubtypeSwitcher.switchToShortcutIME(); break; - case Keyboard.CODE_TAB: - handleTab(); - // There are two cases for tab. Either we send a "next" event, that may change the - // focus but will never move the cursor. Or, we send a real tab keycode, which some - // applications may accept or ignore, and we don't know whether this will move the - // cursor or not. So actually, we don't really know. - // So to go with the safer option, we'd rather behave as if the user moved the - // cursor when they didn't than the opposite. We also expect that most applications - // will actually use tab only for focus movement. - // To sum it up: do not update mExpectingUpdateSelection here. + case Keyboard.CODE_ACTION_ENTER: + performeEditorAction(getActionId(switcher.getKeyboard())); + break; + case Keyboard.CODE_ACTION_NEXT: + performeEditorAction(EditorInfo.IME_ACTION_NEXT); + break; + case Keyboard.CODE_ACTION_PREVIOUS: + EditorInfoCompatUtils.performEditorActionPrevious(getCurrentInputConnection()); + break; + case Keyboard.CODE_LANGUAGE_SWITCH: + handleLanguageSwitchKey(); break; default: + mSpaceState = SPACE_STATE_NONE; if (mSettingsValues.isWordSeparator(primaryCode)) { - handleSeparator(primaryCode, x, y); + didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); } else { - handleCharacter(primaryCode, keyCodes, x, y); + handleCharacter(primaryCode, x, y, spaceState); } mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; break; } - switcher.onKey(primaryCode); + switcher.onCodeInput(primaryCode); // Reset after any single keystroke + if (!didAutoCorrect) + mLastComposedWord.deactivate(); mEnteredText = null; - if (shouldStartKeyTypedTimer) { - mHandler.startKeyTypedTimer(); - } } @Override @@ -1368,15 +1344,38 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; ic.beginBatchEdit(); - commitTyped(ic); - maybeRemovePreviousPeriod(ic, text); + commitTyped(ic, LastComposedWord.NOT_A_SEPARATOR); + text = specificTldProcessingOnTextInput(ic, text); + if (SPACE_STATE_PHANTOM == mSpaceState) { + sendKeyCodePoint(Keyboard.CODE_SPACE); + } ic.commitText(text, 1); ic.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); - mKeyboardSwitcher.onKey(Keyboard.CODE_DUMMY); - mJustAddedMagicSpace = false; + mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); + mSpaceState = SPACE_STATE_NONE; mEnteredText = text; - mHandler.startKeyTypedTimer(); + resetComposingState(true /* alsoResetLastComposedWord */); + } + + // ic may not be null + private CharSequence specificTldProcessingOnTextInput(final InputConnection ic, + final CharSequence text) { + if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD + || !Character.isLetter(text.charAt(1))) { + // Not a tld: do nothing. + return text; + } + // We have a TLD (or something that looks like this): make sure we don't add + // a space even if currently in phantom mode. + mSpaceState = SPACE_STATE_NONE; + final CharSequence lastOne = ic.getTextBeforeCursor(1, 0); + if (lastOne != null && lastOne.length() == 1 + && lastOne.charAt(0) == Keyboard.CODE_PERIOD) { + return text.subSequence(1, text.length()); + } else { + return text; + } } @Override @@ -1385,176 +1384,194 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mKeyboardSwitcher.onCancelInput(); } - private void handleBackspace(boolean justReplacedDoubleSpace) { + private void handleBackspace(final int spaceState) { if (mVoiceProxy.logAndRevertVoiceInput()) return; - final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; ic.beginBatchEdit(); + handleBackspaceWhileInBatchEdit(spaceState, ic); + ic.endBatchEdit(); + } + // "ic" may not be null. + private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { mVoiceProxy.handleBackspace(); - final boolean deleteChar = !mHasUncommittedTypedChars; - if (mHasUncommittedTypedChars) { - final int length = mComposingStringBuilder.length(); + // In many cases, we may have to put the keyboard in auto-shift state again. + mHandler.postUpdateShiftState(); + + if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { + // Cancel multi-character input: remove the text we just entered. + // This is triggered on backspace after a key that inputs multiple characters, + // like the smiley key or the .com key. + ic.deleteSurroundingText(mEnteredText.length(), 0); + // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false. + // In addition we know that spaceState is false, and that we should not be + // reverting any autocorrect at this point. So we can safely return. + return; + } + + if (mWordComposer.isComposingWord()) { + final int length = mWordComposer.size(); if (length > 0) { - mComposingStringBuilder.delete(length - 1, length); mWordComposer.deleteLast(); - final CharSequence textWithUnderline = - mComposingStateManager.isAutoCorrectionIndicatorOn() - ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( - this, mComposingStringBuilder) - : mComposingStringBuilder; - ic.setComposingText(textWithUnderline, 1); - if (mComposingStringBuilder.length() == 0) { - mHasUncommittedTypedChars = false; - } - if (1 == length) { - // 1 == length means we are about to erase the last character of the word, - // so we can show bigrams. + ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); + // If we have deleted the last remaining character of a word, then we are not + // isComposingWord() any more. + if (!mWordComposer.isComposingWord()) { + // Not composing word any more, so we can show bigrams. mHandler.postUpdateBigramPredictions(); } else { - // length > 1, so we still have letters to deduce a suggestion from. + // Still composing a word, so we still have letters to deduce a suggestion from. mHandler.postUpdateSuggestions(); } } else { ic.deleteSurroundingText(1, 0); } - } - mHandler.postUpdateShiftKeyState(); - - TextEntryState.backspace(); - if (TextEntryState.isUndoCommit()) { - revertLastWord(ic); - ic.endBatchEdit(); - return; - } - if (justReplacedDoubleSpace) { - if (revertDoubleSpace(ic)) { - ic.endBatchEdit(); + } else { + if (mLastComposedWord.canRevertCommit()) { + Utils.Stats.onAutoCorrectionCancellation(); + revertCommit(ic); return; } - } + if (SPACE_STATE_DOUBLE == spaceState) { + if (revertDoubleSpaceWhileInBatchEdit(ic)) { + // No need to reset mSpaceState, it has already be done (that's why we + // receive it as a parameter) + return; + } + } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) { + if (revertSwapPunctuation(ic)) { + // Likewise + return; + } + } - if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { - ic.deleteSurroundingText(mEnteredText.length(), 0); - } else if (deleteChar) { - if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { - // Go back to the suggestion mode if the user canceled the - // "Touch again to save". - // NOTE: In gerenal, we don't revert the word when backspacing - // from a manual suggestion pick. We deliberately chose a - // different behavior only in the case of picking the first - // suggestion (typed word). It's intentional to have made this - // inconsistent with backspacing after selecting other suggestions. - revertLastWord(ic); + // No cancelling of commit/double space/swap: we have a regular backspace. + // We should backspace one char and restart suggestion if at the end of a word. + if (mLastSelectionStart != mLastSelectionEnd) { + // If there is a selection, remove it. + final int lengthToDelete = mLastSelectionEnd - mLastSelectionStart; + ic.setSelection(mLastSelectionEnd, mLastSelectionEnd); + ic.deleteSurroundingText(lengthToDelete, 0); } else { - sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + // There is no selection, just delete one character. + if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) { + // This should never happen. + Log.e(TAG, "Backspace when we don't know the selection position"); + } + ic.deleteSurroundingText(1, 0); if (mDeleteCount > DELETE_ACCELERATE_AT) { - sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + ic.deleteSurroundingText(1, 0); } } + if (isSuggestionsRequested()) { + restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic); + } } - ic.endBatchEdit(); } - private void handleTab() { - final int imeOptions = getCurrentInputEditorInfo().imeOptions; - if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) - && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { - sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); - return; - } - - final InputConnection ic = getCurrentInputConnection(); - if (ic == null) - return; - - // True if keyboard is in either chording shift or manual temporary upper case mode. - final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); - if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) - && !isManualTemporaryUpperCase) { - EditorInfoCompatUtils.performEditorActionNext(ic); - } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) - && isManualTemporaryUpperCase) { - EditorInfoCompatUtils.performEditorActionPrevious(ic); + // ic may be null + private boolean maybeStripSpaceWhileInBatchEdit(final InputConnection ic, final int code, + final int spaceState, final boolean isFromSuggestionStrip) { + if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) { + removeTrailingSpaceWhileInBatchEdit(ic); + return false; + } else if ((SPACE_STATE_WEAK == spaceState + || SPACE_STATE_SWAP_PUNCTUATION == spaceState) + && isFromSuggestionStrip) { + if (mSettingsValues.isWeakSpaceSwapper(code)) { + return true; + } else { + if (mSettingsValues.isWeakSpaceStripper(code)) { + removeTrailingSpaceWhileInBatchEdit(ic); + } + return false; + } + } else { + return false; } } - private void handleCharacter(int primaryCode, int[] keyCodes, int x, int y) { + private void handleCharacter(final int primaryCode, final int x, + final int y, final int spaceState) { mVoiceProxy.handleCharacter(); - - if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) { - removeTrailingSpace(); + final InputConnection ic = getCurrentInputConnection(); + if (null != ic) ic.beginBatchEdit(); + // TODO: if ic is null, does it make any sense to call this? + handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic); + if (null != ic) ic.endBatchEdit(); + } + + // "ic" may be null without this crashing, but the behavior will be really strange + private void handleCharacterWhileInBatchEdit(final int primaryCode, + final int x, final int y, final int spaceState, final InputConnection ic) { + boolean isComposingWord = mWordComposer.isComposingWord(); + + if (SPACE_STATE_PHANTOM == spaceState && + !mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) { + if (isComposingWord) { + // Sanity check + throw new RuntimeException("Should not be composing here"); + } + sendKeyCodePoint(Keyboard.CODE_SPACE); } - int code = primaryCode; - if ((isAlphabet(code) || mSettingsValues.isSymbolExcludedFromWordSeparators(code)) + if ((isAlphabet(primaryCode) + || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) && isSuggestionsRequested() && !isCursorTouchingWord()) { - if (!mHasUncommittedTypedChars) { - mHasUncommittedTypedChars = true; - mComposingStringBuilder.setLength(0); - mWordComposer.reset(); + if (!isComposingWord) { + // Reset entirely the composing state anyway, then start composing a new word unless + // the character is a single quote. The idea here is, single quote is not a + // separator and it should be treated as a normal character, except in the first + // position where it should not start composing a word. + isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); + // Here we don't need to reset the last composed word. It will be reset + // when we commit this one, if we ever do; if on the other hand we backspace + // it entirely and resume suggestions on the previous word, we'd like to still + // have touch coordinates for it. + resetComposingState(false /* alsoResetLastComposedWord */); clearSuggestions(); - mComposingStateManager.onFinishComposingText(); - } - } - final KeyboardSwitcher switcher = mKeyboardSwitcher; - if (switcher.isShiftedOrShiftLocked()) { - if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT - || keyCodes[0] > Character.MAX_CODE_POINT) { - return; - } - code = keyCodes[0]; - if (switcher.isAlphabetMode() && Character.isLowerCase(code)) { - // In some locales, such as Turkish, Character.toUpperCase() may return a wrong - // character because it doesn't take care of locale. - final String upperCaseString = new String(new int[] {code}, 0, 1) - .toUpperCase(mSubtypeSwitcher.getInputLocale()); - if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { - code = upperCaseString.codePointAt(0); - } else { - // Some keys, such as [eszett], have upper case as multi-characters. - onTextInput(upperCaseString); - return; - } } } - if (mHasUncommittedTypedChars) { - mComposingStringBuilder.append((char) code); - mWordComposer.add(code, keyCodes, x, y); - final InputConnection ic = getCurrentInputConnection(); + if (isComposingWord) { + mWordComposer.add( + primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector()); if (ic != null) { // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { mWordComposer.setAutoCapitalized(getCurrentAutoCapsState()); - mComposingStateManager.onStartComposingText(); } - final CharSequence textWithUnderline = - mComposingStateManager.isAutoCorrectionIndicatorOn() - ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( - this, mComposingStringBuilder) - : mComposingStringBuilder; - ic.setComposingText(textWithUnderline, 1); + ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } mHandler.postUpdateSuggestions(); } else { - sendKeyChar((char)code); - } - if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceSwapper(primaryCode)) { - swapSwapperAndSpace(); - } else { - mJustAddedMagicSpace = false; - } + final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, + spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); + + sendKeyCodePoint(primaryCode); - switcher.updateShiftState(); - if (LatinIME.PERF_DEBUG) measureCps(); - TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); + if (swapWeakSpace) { + swapSwapperAndSpaceWhileInBatchEdit(ic); + mSpaceState = SPACE_STATE_WEAK; + } + // Some characters are not word separators, yet they don't start a new + // composing span. For these, we haven't changed the suggestion strip, and + // if the "add to dictionary" hint is shown, we should do so now. Examples of + // such characters include single quote, dollar, and others; the exact list is + // the list of characters for which we enter handleCharacterWhileInBatchEdit + // that don't match the test if ((isAlphabet...)) at the top of this method. + if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) { + mHandler.postUpdateBigramPredictions(); + } + } + Utils.Stats.onNonSeparator((char)primaryCode, x, y); } - private void handleSeparator(int primaryCode, int x, int y) { + // Returns true if we did an autocorrection, false otherwise. + private boolean handleSeparator(final int primaryCode, final int x, final int y, + final int spaceState) { mVoiceProxy.handleSeparator(); - mComposingStateManager.onFinishComposingText(); // Should dismiss the "Touch again to save" message when handling separator if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { @@ -1562,71 +1579,85 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.postUpdateSuggestions(); } - boolean pickedDefault = false; + boolean didAutoCorrect = false; // Handle separator final InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.beginBatchEdit(); } - if (mHasUncommittedTypedChars) { + if (mWordComposer.isComposingWord()) { // In certain languages where single quote is a separator, it's better // not to auto correct, but accept the typed word. For instance, // in Italian dov' should not be expanded to dove' because the elision // requires the last vowel to be removed. final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled - && !mInputTypeNoAutoCorrect; + && !mInputAttributes.mInputTypeNoAutoCorrect; if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { - pickedDefault = pickDefaultSuggestion(primaryCode); + commitCurrentAutoCorrection(primaryCode, ic); + didAutoCorrect = true; } else { - commitTyped(ic); + commitTyped(ic, primaryCode); } } - if (mJustAddedMagicSpace) { - if (mSettingsValues.isMagicSpaceSwapper(primaryCode)) { - sendKeyChar((char)primaryCode); - swapSwapperAndSpace(); - } else { - if (mSettingsValues.isMagicSpaceStripper(primaryCode)) removeTrailingSpace(); - sendKeyChar((char)primaryCode); - mJustAddedMagicSpace = false; - } - } else { - sendKeyChar((char)primaryCode); - } + final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); - if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { - maybeDoubleSpace(); + if (SPACE_STATE_PHANTOM == spaceState && + mSettingsValues.isPhantomSpacePromotingSymbol(primaryCode)) { + sendKeyCodePoint(Keyboard.CODE_SPACE); } + sendKeyCodePoint(primaryCode); - TextEntryState.typedCharacter((char) primaryCode, true, x, y); - - if (pickedDefault) { - CharSequence typedWord = mWordComposer.getTypedWord(); - TextEntryState.backToAcceptedDefault(typedWord); - if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { - InputConnectionCompatUtils.commitCorrection( - ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); - } - } if (Keyboard.CODE_SPACE == primaryCode) { + if (isSuggestionsRequested()) { + if (maybeDoubleSpaceWhileInBatchEdit(ic)) { + mSpaceState = SPACE_STATE_DOUBLE; + } else if (!isShowingPunctuationList()) { + mSpaceState = SPACE_STATE_WEAK; + } + } + + mHandler.startDoubleSpacesTimer(); if (!isCursorTouchingWord()) { mHandler.cancelUpdateSuggestions(); mHandler.postUpdateBigramPredictions(); } } else { + if (swapWeakSpace) { + swapSwapperAndSpaceWhileInBatchEdit(ic); + mSpaceState = SPACE_STATE_SWAP_PUNCTUATION; + } else if (SPACE_STATE_PHANTOM == spaceState) { + // If we are in phantom space state, and the user presses a separator, we want to + // stay in phantom space state so that the next keypress has a chance to add the + // space. For example, if I type "Good dat", pick "day" from the suggestion strip + // then insert a comma and go on to typing the next word, I want the space to be + // inserted automatically before the next word, the same way it is when I don't + // input the comma. + mSpaceState = SPACE_STATE_PHANTOM; + } + // Set punctuation right away. onUpdateSelection will fire but tests whether it is // already displayed or not, so it's okay. setPunctuationSuggestions(); } - mKeyboardSwitcher.updateShiftState(); + + Utils.Stats.onSeparator((char)primaryCode, x, y); + if (ic != null) { ic.endBatchEdit(); } + return didAutoCorrect; + } + + private CharSequence getTextWithUnderline(final CharSequence text) { + return mIsAutoCorrectionIndicatorOn + ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) + : text; } private void handleClose() { - commitTyped(getCurrentInputConnection()); + commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); mVoiceProxy.handleClose(); requestHideSelf(0); LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); @@ -1635,7 +1666,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public boolean isSuggestionsRequested() { - return mIsSettingsSuggestionStripOn + return mInputAttributes.mIsSettingsSuggestionStripOn && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); } @@ -1653,11 +1684,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public boolean isSuggestionsStripVisible() { if (mSuggestionsView == null) return false; - if (mSuggestionsView.isShowingAddToDictionaryHint() || TextEntryState.isRecorrecting()) + if (mSuggestionsView.isShowingAddToDictionaryHint()) return true; if (!isShowingSuggestionsStrip()) return false; - if (mApplicationSpecifiedCompletionOn) + if (mInputAttributes.mApplicationSpecifiedCompletionOn) return true; return isSuggestionsRequested(); } @@ -1681,36 +1712,27 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public void clearSuggestions() { - setSuggestions(SuggestedWords.EMPTY); + setSuggestions(SuggestedWords.EMPTY, false); + setAutoCorrectionIndicator(false); } - public void setSuggestions(SuggestedWords words) { + private void setSuggestions(final SuggestedWords words, final boolean isAutoCorrection) { if (mSuggestionsView != null) { mSuggestionsView.setSuggestions(words); - mKeyboardSwitcher.onAutoCorrectionStateChanged( - words.hasWordAboveAutoCorrectionScoreThreshold()); + mKeyboardSwitcher.onAutoCorrectionStateChanged(isAutoCorrection); } + } + private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) { // Put a blue underline to a word in TextView which will be auto-corrected. final InputConnection ic = getCurrentInputConnection(); - if (ic != null) { - final boolean oldAutoCorrectionIndicator = - mComposingStateManager.isAutoCorrectionIndicatorOn(); - final boolean newAutoCorrectionIndicator = Utils.willAutoCorrect(words); - if (oldAutoCorrectionIndicator != newAutoCorrectionIndicator) { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator - + " -> " + newAutoCorrectionIndicator); - } - final CharSequence textWithUnderline = newAutoCorrectionIndicator - ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline( - this, mComposingStringBuilder) - : mComposingStringBuilder; - if (!TextUtils.isEmpty(textWithUnderline)) { - ic.setComposingText(textWithUnderline, 1); - } - mComposingStateManager.setAutoCorrectionIndicatorOn(newAutoCorrectionIndicator); - } + if (ic == null) return; + if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator + && mWordComposer.isComposingWord()) { + mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator; + final CharSequence textWithUnderline = + getTextWithUnderline(mWordComposer.getTypedWord()); + ic.setComposingText(textWithUnderline, 1); } } @@ -1718,18 +1740,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Check if we have a suggestion engine attached. if ((mSuggest == null || !isSuggestionsRequested()) && !mVoiceProxy.isVoiceInputHighlighted()) { + if (mWordComposer.isComposingWord()) { + Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); + mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); + } return; } mHandler.cancelUpdateSuggestions(); mHandler.cancelUpdateBigramPredictions(); - if (!mHasUncommittedTypedChars) { + if (!mWordComposer.isComposingWord()) { setPunctuationSuggestions(); return; } - final WordComposer wordComposer = mWordComposer; // TODO: May need a better way of retrieving previous word final InputConnection ic = getCurrentInputConnection(); final CharSequence prevWord; @@ -1738,27 +1763,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); } - // getSuggestedWordBuilder handles gracefully a null value of prevWord - final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( - wordComposer, prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); - - boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); - final CharSequence typedWord = wordComposer.getTypedWord(); - // Here, we want to promote a whitelisted word if exists. - // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" - // but still autocorrected from - in the case the whitelist only capitalizes the word. - // The whitelist should be case-insensitive, so it's not possible to be consistent with - // a boolean flag. Right now this is handled with a slight hack in - // WhitelistDictionary#shouldForciblyAutoCorrectFrom. - final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( - mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); - if (mCorrectionMode == Suggest.CORRECTION_FULL - || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { - autoCorrectionAvailable |= (!allowsToBeAutoCorrected); - } - // Don't auto-correct words with multiple capital letter - autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); - autoCorrectionAvailable &= !TextEntryState.isRecorrecting(); + + final CharSequence typedWord = mWordComposer.getTypedWord(); + // getSuggestedWords handles gracefully a null value of prevWord + final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, + prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), mCorrectionMode); // Basically, we update the suggestion strip only when suggestion count > 1. However, // there is an exception: We update the suggestion strip whenever typed word's length @@ -1766,131 +1775,126 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // in most cases, suggestion count is 1 when typed word's length is 1, but we do always // need to clear the previous state when the user starts typing a word (i.e. typed word's // length == 1). - if (typedWord != null) { - if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) - || mSuggestionsView.isShowingAddToDictionaryHint()) { - builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( - autoCorrectionAvailable); - } else { - SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); - if (previousSuggestions == mSettingsValues.mSuggestPuncList) { - if (builder.size() == 0) { - return; - } - previousSuggestions = SuggestedWords.EMPTY; - } - builder.addTypedWordAndPreviousSuggestions(typedWord, previousSuggestions); + if (suggestedWords.size() > 1 || typedWord.length() == 1 + || !suggestedWords.mAllowsToBeAutoCorrected + || mSuggestionsView.isShowingAddToDictionaryHint()) { + showSuggestions(suggestedWords, typedWord); + } else { + SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); + if (previousSuggestions == mSettingsValues.mSuggestPuncList) { + previousSuggestions = SuggestedWords.EMPTY; } - } - showSuggestions(builder.build(), typedWord); - } - - public void showSuggestions(SuggestedWords suggestedWords, CharSequence typedWord) { - final boolean shouldBlockAutoCorrectionBySafetyNet = - Utils.shouldBlockAutoCorrectionBySafetyNet(suggestedWords, mSuggest); - if (shouldBlockAutoCorrectionBySafetyNet) { - suggestedWords.setShouldBlockAutoCorrection(); - } - setSuggestions(suggestedWords); + final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = + SuggestedWords.getTypedWordAndPreviousSuggestions( + typedWord, previousSuggestions); + final SuggestedWords obsoleteSuggestedWords = + new SuggestedWords(typedWordAndPreviousSuggestions, + false /* typedWordValid */, + false /* hasAutoCorrectionCandidate */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */, + true /* isObsoleteSuggestions */); + showSuggestions(obsoleteSuggestedWords, typedWord); + } + } + + public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) { + final CharSequence autoCorrection; if (suggestedWords.size() > 0) { - if (shouldBlockAutoCorrectionBySafetyNet) { - mBestWord = typedWord; - } else if (suggestedWords.hasAutoCorrectionWord()) { - mBestWord = suggestedWords.getWord(1); + if (suggestedWords.hasAutoCorrectionWord()) { + autoCorrection = suggestedWords.getWord(1); } else { - mBestWord = typedWord; + autoCorrection = typedWord; } } else { - mBestWord = null; + autoCorrection = null; } + mWordComposer.setAutoCorrection(autoCorrection); + final boolean isAutoCorrection = suggestedWords.willAutoCorrect(); + setSuggestions(suggestedWords, isAutoCorrection); + setAutoCorrectionIndicator(isAutoCorrection); setSuggestionStripShown(isSuggestionsStripVisible()); } - private boolean pickDefaultSuggestion(int separatorCode) { + private void commitCurrentAutoCorrection(final int separatorCodePoint, + final InputConnection ic) { // Complete any pending suggestions query first if (mHandler.hasPendingUpdateSuggestions()) { mHandler.cancelUpdateSuggestions(); updateSuggestions(); } - if (mBestWord != null && mBestWord.length() > 0) { - TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode); + final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); + if (autoCorrection != null) { + final String typedWord = mWordComposer.getTypedWord(); + if (TextUtils.isEmpty(typedWord)) { + throw new RuntimeException("We have an auto-correction but the typed word " + + "is empty? Impossible! I must commit suicide."); + } + Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); mExpectingUpdateSelection = true; - commitBestWord(mBestWord); + commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, + separatorCodePoint); // Add the word to the user unigram dictionary if it's not a known word - addToUserUnigramAndBigramDictionaries(mBestWord, + addToUserUnigramAndBigramDictionaries(autoCorrection, UserUnigramDictionary.FREQUENCY_FOR_TYPED); - return true; + if (!typedWord.equals(autoCorrection) && null != ic) { + // This will make the correction flash for a short while as a visual clue + // to the user that auto-correction happened. + InputConnectionCompatUtils.commitCorrection(ic, + mLastSelectionEnd - typedWord.length(), typedWord, autoCorrection); + } } - return false; } @Override - public void pickSuggestionManually(int index, CharSequence suggestion) { - mComposingStateManager.onFinishComposingText(); - SuggestedWords suggestions = mSuggestionsView.getSuggestions(); + public void pickSuggestionManually(final int index, final CharSequence suggestion) { + final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, mSettingsValues.mWordSeparators); - final boolean recorrecting = TextEntryState.isRecorrecting(); - final InputConnection ic = getCurrentInputConnection(); - if (ic != null) { - ic.beginBatchEdit(); + if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { + int firstChar = Character.codePointAt(suggestion, 0); + if ((!mSettingsValues.isWeakSpaceStripper(firstChar)) + && (!mSettingsValues.isWeakSpaceSwapper(firstChar))) { + sendKeyCodePoint(Keyboard.CODE_SPACE); + } } - if (mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null + + if (mInputAttributes.mApplicationSpecifiedCompletionOn + && mApplicationSpecifiedCompletions != null && index >= 0 && index < mApplicationSpecifiedCompletions.length) { - if (ic != null) { - final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; - ic.commitCompletion(completionInfo); - } - mCommittedLength = suggestion.length(); if (mSuggestionsView != null) { mSuggestionsView.clear(); } mKeyboardSwitcher.updateShiftState(); + resetComposingState(true /* alsoResetLastComposedWord */); + final InputConnection ic = getCurrentInputConnection(); if (ic != null) { - ic.endBatchEdit(); + final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; + ic.commitCompletion(completionInfo); } return; } - // If this is a punctuation, apply it through the normal key press - if (suggestion.length() == 1 && (mSettingsValues.isWordSeparator(suggestion.charAt(0)) - || mSettingsValues.isSuggestedPunctuation(suggestion.charAt(0)))) { + // 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. // So, LatinImeLogger logs "" as a user's input. - LatinImeLogger.logOnManualSuggestion( - "", suggestion.toString(), index, suggestions.mWords); - // Find out whether the previous character is a space. If it is, as a special case - // for punctuation entered through the suggestion strip, it should be considered - // a magic space even if it was a normal space. This is meant to help in case the user - // pressed space on purpose of displaying the suggestion strip punctuation. - final int rawPrimaryCode = suggestion.charAt(0); - // Maybe apply the "bidi mirrored" conversions for parentheses - final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); - final boolean isRtl = keyboard != null && keyboard.mIsRtlKeyboard; - final int primaryCode = Key.getRtlParenthesisCode(rawPrimaryCode, isRtl); - - final CharSequence beforeText = ic != null ? ic.getTextBeforeCursor(1, 0) : ""; - final int toLeft = (ic == null || TextUtils.isEmpty(beforeText)) - ? 0 : beforeText.charAt(0); - final boolean oldMagicSpace = mJustAddedMagicSpace; - if (Keyboard.CODE_SPACE == toLeft) mJustAddedMagicSpace = true; - onCodeInput(primaryCode, new int[] { primaryCode }, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE, - KeyboardActionListener.NOT_A_TOUCH_COORDINATE); - mJustAddedMagicSpace = oldMagicSpace; - if (ic != null) { - ic.endBatchEdit(); - } + LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); + // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. + final int primaryCode = suggestion.charAt(0); + onCodeInput(primaryCode, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, + KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); return; } - if (!mHasUncommittedTypedChars) { - // If we are not composing a word, then it was a suggestion inferred from - // context - no user input. We should reset the word composer. - mWordComposer.reset(); - } + // We need to log before we commit, because the word composer will store away the user + // typed word. + LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), + suggestion.toString(), index, suggestedWords); mExpectingUpdateSelection = true; - commitBestWord(suggestion); + commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, + LastComposedWord.NOT_A_SEPARATOR); // Add the word to the auto dictionary if it's not a known word if (index == 0) { addToUserUnigramAndBigramDictionaries(suggestion, @@ -1898,13 +1902,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { addToOnlyBigramDictionary(suggestion, 1); } - LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(), - suggestion.toString(), index, suggestions.mWords); - TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion); - // Follow it with a space - if (mInsertSpaceOnPickSuggestionManually && !recorrecting) { - sendMagicSpace(); - } + mSpaceState = SPACE_STATE_PHANTOM; + // TODO: is this necessary? + mKeyboardSwitcher.updateShiftState(); // We should show the "Touch again to save" hint if the user pressed the first entry // AND either: @@ -1922,13 +1922,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar || !AutoCorrection.isValidWord( mSuggest.getUnigramDictionaries(), suggestion, true)); - if (!recorrecting) { - // Fool the state watcher so that a subsequent backspace will not do a revert, unless - // we just did a correction, in which case we need to stay in - // TextEntryState.State.PICKED_SUGGESTION state. - TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); - } + Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, + WordComposer.NOT_A_COORDINATE); if (!showingAddToDictionaryHint) { // If we're not showing the "Touch again to save", then show corrections again. // In case the cursor position doesn't change, make sure we show the suggestions again. @@ -1936,26 +1931,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Updating the predictions right away may be slow and feel unresponsive on slower // terminals. On the other hand if we just postUpdateBigramPredictions() it will // take a noticeable delay to update them which may feel uneasy. - } - if (showingAddToDictionaryHint) { - if (mIsUserDictionaryAvaliable) { - mSuggestionsView.showAddToDictionaryHint(suggestion); + } else { + if (mIsUserDictionaryAvailable) { + mSuggestionsView.showAddToDictionaryHint( + suggestion, mSettingsValues.mHintToSaveText); } else { mHandler.postUpdateSuggestions(); } } - if (ic != null) { - ic.endBatchEdit(); - } } /** * Commits the chosen word to the text field and saves it for later retrieval. */ - private void commitBestWord(CharSequence bestWord) { - final KeyboardSwitcher switcher = mKeyboardSwitcher; - if (!switcher.isKeyboardAvailable()) - return; + private void commitChosenWord(final CharSequence bestWord, final int commitType, + final int separatorCode) { final InputConnection ic = getCurrentInputConnection(); if (ic != null) { mVoiceProxy.rememberReplacedWord(bestWord, mSettingsValues.mWordSeparators); @@ -1967,11 +1957,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.commitText(bestWord, 1); } } - mHasUncommittedTypedChars = false; - mCommittedLength = bestWord.length(); + // TODO: figure out here if this is an auto-correct or if the best word is actually + // what user typed. Note: currently this is done much later in + // LastComposedWord#didCommitTypedWord by string equality of the remembered + // strings. + mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(), + separatorCode); } - private static final WordComposer sEmptyWordComposer = new WordComposer(); public void updateBigramPredictions() { if (mSuggest == null || !isSuggestionsRequested()) return; @@ -1981,22 +1974,31 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return; } - final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), - mSettingsValues.mWordSeparators); - SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer, - prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo()); + final SuggestedWords suggestedWords; + if (mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { + final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), + mSettingsValues.mWordSeparators); + if (!TextUtils.isEmpty(prevWord)) { + suggestedWords = mSuggest.getBigramPredictions(prevWord); + } else { + suggestedWords = null; + } + } else { + suggestedWords = null; + } - if (builder.size() > 0) { + if (null != suggestedWords && suggestedWords.size() > 0) { // Explicitly supply an empty typed word (the no-second-arg version of // showSuggestions will retrieve the word near the cursor, we don't want that here) - showSuggestions(builder.build(), ""); + showSuggestions(suggestedWords, ""); } else { if (!isShowingPunctuationList()) setPunctuationSuggestions(); } } public void setPunctuationSuggestions() { - setSuggestions(mSettingsValues.mSuggestPuncList); + setSuggestions(mSettingsValues.mSuggestPuncList, false); + setAutoCorrectionIndicator(false); setSuggestionStripShown(isSuggestionsStripVisible()); } @@ -2055,72 +2057,157 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public boolean isCursorTouchingWord() { final InputConnection ic = getCurrentInputConnection(); if (ic == null) return false; - CharSequence toLeft = ic.getTextBeforeCursor(1, 0); - CharSequence toRight = ic.getTextAfterCursor(1, 0); - if (!TextUtils.isEmpty(toLeft) - && !mSettingsValues.isWordSeparator(toLeft.charAt(0)) - && !mSettingsValues.isSuggestedPunctuation(toLeft.charAt(0))) { + CharSequence before = ic.getTextBeforeCursor(1, 0); + CharSequence after = ic.getTextAfterCursor(1, 0); + if (!TextUtils.isEmpty(before) && !mSettingsValues.isWordSeparator(before.charAt(0)) + && !mSettingsValues.isSymbolExcludedFromWordSeparators(before.charAt(0))) { return true; } - if (!TextUtils.isEmpty(toRight) - && !mSettingsValues.isWordSeparator(toRight.charAt(0)) - && !mSettingsValues.isSuggestedPunctuation(toRight.charAt(0))) { + if (!TextUtils.isEmpty(after) && !mSettingsValues.isWordSeparator(after.charAt(0)) + && !mSettingsValues.isSymbolExcludedFromWordSeparators(after.charAt(0))) { return true; } return false; } - // "ic" must not null - private boolean sameAsTextBeforeCursor(final InputConnection ic, CharSequence text) { - CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); + // "ic" must not be null + private static boolean sameAsTextBeforeCursor(final InputConnection ic, + final CharSequence text) { + final CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); return TextUtils.equals(text, beforeText); } - // "ic" must not null - private void revertLastWord(final InputConnection ic) { - if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) { - sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + // "ic" must not be null + /** + * Check if the cursor is actually at the end of a word. If so, restart suggestions on this + * word, else do nothing. + */ + private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord( + final InputConnection ic) { + // Bail out if the cursor is not at the end of a word (cursor must be preceded by + // non-whitespace, non-separator, non-start-of-text) + // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here. + final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0); + if (TextUtils.isEmpty(textBeforeCursor) + || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return; + + // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace, + // separator or end of line/text) + // Example: "test|"<EOL> "te|st" get rejected here + final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0); + if (!TextUtils.isEmpty(textAfterCursor) + && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return; + + // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe) + // Example: " -|" gets rejected here but "e-|" and "e|" are okay + CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators); + // We don't suggest on leading single quotes, so we have to remove them from the word if + // it starts with single quotes. + while (!TextUtils.isEmpty(word) && Keyboard.CODE_SINGLE_QUOTE == word.charAt(0)) { + word = word.subSequence(1, word.length()); + } + if (TextUtils.isEmpty(word)) return; + final char firstChar = word.charAt(0); // we just tested that word is not empty + if (word.length() == 1 && !Character.isLetter(firstChar)) return; + + // We only suggest on words that start with a letter or a symbol that is excluded from + // word separators (see #handleCharacterWhileInBatchEdit). + if (!(isAlphabet(firstChar) + || mSettingsValues.isSymbolExcludedFromWordSeparators(firstChar))) { return; } - final CharSequence separator = ic.getTextBeforeCursor(1, 0); - ic.deleteSurroundingText(1, 0); - final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); - ic.deleteSurroundingText(mCommittedLength, 0); - - // Re-insert "separator" only when the deleted character was word separator and the - // composing text wasn't equal to the auto-corrected text which can be found before - // the cursor. - if (!TextUtils.isEmpty(separator) - && mSettingsValues.isWordSeparator(separator.charAt(0)) - && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) { - ic.commitText(mComposingStringBuilder, 1); - TextEntryState.acceptedTyped(mComposingStringBuilder); - ic.commitText(separator, 1); - TextEntryState.typedCharacter(separator.charAt(0), true, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); - // Clear composing text - mComposingStringBuilder.setLength(0); - } else { - mHasUncommittedTypedChars = true; - ic.setComposingText(mComposingStringBuilder, 1); - TextEntryState.backspace(); + // Okay, we are at the end of a word. Restart suggestions. + restartSuggestionsOnWordBeforeCursor(ic, word); + } + + // "ic" must not be null + private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic, + final CharSequence word) { + mWordComposer.setComposingWord(word, mKeyboardSwitcher.getKeyboard()); + ic.deleteSurroundingText(word.length(), 0); + ic.setComposingText(word, 1); + mHandler.postUpdateSuggestions(); + } + + // "ic" must not be null + private void revertCommit(final InputConnection ic) { + final String originallyTypedWord = mLastComposedWord.mTypedWord; + final CharSequence committedWord = mLastComposedWord.mCommittedWord; + final int cancelLength = committedWord.length(); + final int separatorLength = LastComposedWord.getSeparatorLength( + mLastComposedWord.mSeparatorCode); + // TODO: should we check our saved separator against the actual contents of the text view? + if (DEBUG) { + if (mWordComposer.isComposingWord()) { + throw new RuntimeException("revertCommit, but we are composing a word"); + } + final String wordBeforeCursor = + ic.getTextBeforeCursor(cancelLength + separatorLength, 0) + .subSequence(0, cancelLength).toString(); + if (!TextUtils.equals(committedWord, wordBeforeCursor)) { + throw new RuntimeException("revertCommit check failed: we thought we were " + + "reverting \"" + committedWord + + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); + } } + ic.deleteSurroundingText(cancelLength + separatorLength, 0); + if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) { + // This is the case when we cancel a manual pick. + // We should restart suggestion on the word right away. + mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); + ic.setComposingText(originallyTypedWord, 1); + } else { + ic.commitText(originallyTypedWord, 1); + // Re-insert the separator + sendKeyCodePoint(mLastComposedWord.mSeparatorCode); + Utils.Stats.onSeparator(mLastComposedWord.mSeparatorCode, WordComposer.NOT_A_COORDINATE, + WordComposer.NOT_A_COORDINATE); + // Don't restart suggestion yet. We'll restart if the user deletes the + // separator. + } + mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } - // "ic" must not null - private boolean revertDoubleSpace(final InputConnection ic) { + // "ic" must not be null + private boolean revertDoubleSpaceWhileInBatchEdit(final InputConnection ic) { mHandler.cancelDoubleSpacesTimer(); // Here we test whether we indeed have a period and a space before us. This should not // be needed, but it's there just in case something went wrong. final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); - if (!". ".equals(textBeforeCursor)) + if (!". ".equals(textBeforeCursor)) { + // Theoretically we should not be coming here if there isn't ". " before the + // cursor, but the application may be changing the text while we are typing, so + // anything goes. We should not crash. + Log.d(TAG, "Tried to revert double-space combo but we didn't find " + + "\". \" just before the cursor."); return false; - ic.beginBatchEdit(); + } ic.deleteSurroundingText(2, 0); ic.commitText(" ", 1); + return true; + } + + private static boolean revertSwapPunctuation(final InputConnection ic) { + // Here we test whether we indeed have a space and something else before us. This should not + // be needed, but it's there just in case something went wrong. + final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); + // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to + // enter surrogate pairs this code will have been removed. + if (TextUtils.isEmpty(textBeforeCursor) + || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { + // We may only come here if the application is changing the text while we are typing. + // This is quite a broken case, but not logically impossible, so we shouldn't crash, + // but some debugging log may be in order. + Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " + + "find a space just before the cursor."); + return false; + } + ic.beginBatchEdit(); + ic.deleteSurroundingText(2, 0); + ic.commitText(" " + textBeforeCursor.subSequence(0, 1), 1); ic.endBatchEdit(); return true; } @@ -2129,12 +2216,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return mSettingsValues.isWordSeparator(code); } - private void sendMagicSpace() { - sendKeyChar((char)Keyboard.CODE_SPACE); - mJustAddedMagicSpace = true; - mKeyboardSwitcher.updateShiftState(); - } - public boolean preferCapitalization() { return mWordComposer.isFirstCharCapitalized(); } @@ -2154,142 +2235,77 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); } initSuggest(); + updateCorrectionMode(); loadSettings(); + // Since we just changed languages, we should re-evaluate suggestions with whatever word + // we are currently composing. If we are not composing anything, we may want to display + // predictions or punctuation signs (which is done by updateBigramPredictions anyway). + if (isCursorTouchingWord()) { + mHandler.postUpdateSuggestions(); + } else { + mHandler.postUpdateBigramPredictions(); + } + } + + public void hapticAndAudioFeedback(final int primaryCode) { + mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView()); } @Override - public void onPress(int primaryCode, boolean withSliding) { - final KeyboardSwitcher switcher = mKeyboardSwitcher; - if (switcher.isVibrateAndSoundFeedbackRequired()) { - vibrate(); - playKeyClick(primaryCode); - } - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onPressShift(withSliding); - } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - switcher.onPressSymbol(); - } else { - switcher.onOtherKeyPressed(); - } + public void onPressKey(int primaryCode) { + mKeyboardSwitcher.onPressKey(primaryCode); } @Override - public void onRelease(int primaryCode, boolean withSliding) { - KeyboardSwitcher switcher = mKeyboardSwitcher; - // Reset any drag flags in the keyboard - final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); - if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { - switcher.onReleaseShift(withSliding); - } else if (distinctMultiTouch && primaryCode == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { - switcher.onReleaseSymbol(); + public void onReleaseKey(int primaryCode, boolean withSliding) { + mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); + + // If accessibility is on, ensure the user receives keyboard state updates. + if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { + switch (primaryCode) { + case Keyboard.CODE_SHIFT: + AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); + break; + case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: + AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); + break; + } } } - // receive ringer mode change and network state change. private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); - if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { - updateRingerMode(); - } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { mSubtypeSwitcher.onNetworkStateChanged(intent); + } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + mFeedbackManager.onRingerModeChanged(); } } }; - // update keypress sound volume - private void updateSoundEffectVolume() { - mFxVolume = Utils.getCurrentKeypressSoundVolume(mPrefs, mResources); - } - - // update flags for silent mode - private void updateRingerMode() { - if (mAudioManager == null) { - mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - if (mAudioManager == null) return; - } - mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); - } - - private void updateKeypressVibrationDuration() { - mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources); - } - - private void playKeyClick(int primaryCode) { - // if mAudioManager is null, we don't have the ringer state yet - // mAudioManager will be set by updateRingerMode - if (mAudioManager == null) { - if (mKeyboardSwitcher.getKeyboardView() != null) { - updateRingerMode(); - } - } - if (isSoundOn()) { - final int sound; - switch (primaryCode) { - case Keyboard.CODE_DELETE: - sound = AudioManager.FX_KEYPRESS_DELETE; - break; - case Keyboard.CODE_ENTER: - sound = AudioManager.FX_KEYPRESS_RETURN; - break; - case Keyboard.CODE_SPACE: - sound = AudioManager.FX_KEYPRESS_SPACEBAR; - break; - default: - sound = AudioManager.FX_KEYPRESS_STANDARD; - break; - } - mAudioManager.playSoundEffect(sound, mFxVolume); - } - } - + // TODO: remove this method when VoiceProxy has been removed public void vibrate() { - if (!mSettingsValues.mVibrateOn) { - return; - } - if (mKeypressVibrationDuration < 0) { - // Go ahead with the system default - LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); - if (inputView != null) { - inputView.performHapticFeedback( - HapticFeedbackConstants.KEYBOARD_TAP, - HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } - } else if (mVibrator != null) { - mVibrator.vibrate(mKeypressVibrationDuration); - } + mFeedbackManager.vibrate(mKeyboardSwitcher.getKeyboardView()); } - public WordComposer getCurrentWord() { - return mWordComposer; - } - - boolean isSoundOn() { - return mSettingsValues.mSoundOn && !mSilentModeOn; + public boolean isAutoCapitalized() { + return mWordComposer.isAutoCapitalized(); } private void updateCorrectionMode() { // TODO: cleanup messy flags final boolean shouldAutoCorrect = mSettingsValues.mAutoCorrectEnabled - && !mInputTypeNoAutoCorrect; - mCorrectionMode = (shouldAutoCorrect && mSettingsValues.mAutoCorrectEnabled) - ? Suggest.CORRECTION_FULL - : (shouldAutoCorrect ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); - mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect - && mSettingsValues.mAutoCorrectEnabled) + && !mInputAttributes.mInputTypeNoAutoCorrect; + mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE; + mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect) ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; - if (mSuggest != null) { - mSuggest.setCorrectionMode(mCorrectionMode); - } } - private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) { - final String suggestionVisiblityStr = prefs.getString( - Settings.PREF_SHOW_SUGGESTIONS_SETTING, - res.getString(R.string.prefs_suggestion_visibility_default_value)); + private void updateSuggestionVisibility(final Resources res) { + final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting; for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) { if (suggestionVisiblityStr.equals(res.getString(visibility))) { mSuggestionVisibility = visibility; @@ -2328,7 +2344,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar switch (position) { case 0: Intent intent = CompatUtils.getInputLanguageSelectionIntent( - mInputMethodId, Intent.FLAG_ACTIVITY_NEW_TASK + SubtypeUtils.getInputMethodId(getPackageName()), + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); @@ -2377,35 +2394,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final Printer p = new PrintWriterPrinter(fout); p.println("LatinIME state :"); - p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); - p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString()); - p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn); + final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); + final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; + p.println(" Keyboard mode = " + keyboardMode); + p.println(" mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn); p.println(" mCorrectionMode=" + mCorrectionMode); - p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars); + p.println(" isComposingWord=" + mWordComposer.isComposingWord()); p.println(" mAutoCorrectEnabled=" + mSettingsValues.mAutoCorrectEnabled); - p.println(" mInsertSpaceOnPickSuggestionManually=" + mInsertSpaceOnPickSuggestionManually); - p.println(" mApplicationSpecifiedCompletionOn=" + mApplicationSpecifiedCompletionOn); - p.println(" TextEntryState.state=" + TextEntryState.getState()); p.println(" mSoundOn=" + mSettingsValues.mSoundOn); p.println(" mVibrateOn=" + mSettingsValues.mVibrateOn); p.println(" mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn); - } - - // Characters per second measurement - - private long mLastCpsTime; - private static final int CPS_BUFFER_SIZE = 16; - private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; - private int mCpsIndex; - - private void measureCps() { - long now = System.currentTimeMillis(); - if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial - mCpsIntervals[mCpsIndex] = now - mLastCpsTime; - mLastCpsTime = now; - mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; - long total = 0; - for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; - System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); + p.println(" mInputAttributes=" + mInputAttributes.toString()); } } diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index ae8eb374b..5390ee39e 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -16,11 +16,11 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.Dictionary.DataType; - import android.content.Context; import android.content.SharedPreferences; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.Keyboard; import java.util.List; @@ -28,12 +28,13 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static boolean sDBG = false; public static boolean sVISUALDEBUG = false; + public static boolean sUsabilityStudy = false; @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { } - public static void init(Context context, SharedPreferences prefs) { + public static void init(LatinIME context, SharedPreferences prefs) { } public static void commit() { @@ -43,8 +44,8 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang } public static void logOnManualSuggestion( - String before, String after, int position, List<CharSequence> suggestions) { - } + String before, String after, int position, SuggestedWords suggestedWords) { + } public static void logOnAutoCorrection(String before, String after, int separatorCode) { } @@ -67,10 +68,13 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void logOnWarning(String warning) { } + public static void onStartInputView(EditorInfo editorInfo) { + } + public static void onStartSuggestion(CharSequence previousWords) { } - public static void onAddSuggestedWord(String word, int typeId, DataType dataType) { + public static void onAddSuggestedWord(String word, int typeId, int dataType) { } public static void onSetKeyboard(Keyboard kb) { @@ -78,4 +82,8 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void onPrintAllUsabilityStudyLogs() { } + + public static boolean isResearcherPackage(Context context) { + return false; + } } diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 773efe709..72391f31e 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -38,20 +38,16 @@ import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.View; -import android.view.inputmethod.EditorInfo; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.android.inputmethod.compat.CompatUtils; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethodcommon.InputMethodSettingsActivity; -import java.util.Arrays; import java.util.Locale; public class Settings extends InputMethodSettingsActivity @@ -61,261 +57,47 @@ public class Settings extends InputMethodSettingsActivity public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false; - public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings"; + // In the same order as xml/prefs.xml + public static final String PREF_GENERAL_SETTINGS = "general_settings"; + public static final String PREF_SUBTYPES_SETTINGS = "subtype_settings"; + public static final String PREF_AUTO_CAP = "auto_cap"; public static final String PREF_VIBRATE_ON = "vibrate_on"; public static final String PREF_SOUND_ON = "sound_on"; - public static final String PREF_KEY_PREVIEW_POPUP_ON = "popup_on"; - public static final String PREF_AUTO_CAP = "auto_cap"; - public static final String PREF_SHOW_SETTINGS_KEY = "show_settings_key"; - public static final String PREF_VOICE_SETTINGS_KEY = "voice_mode"; - public static final String PREF_INPUT_LANGUAGE = "input_language"; - public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; - public static final String PREF_SUBTYPES = "subtype_settings"; - + public static final String PREF_POPUP_ON = "popup_on"; + public static final String PREF_VOICE_MODE = "voice_mode"; + public static final String PREF_CORRECTION_SETTINGS = "correction_settings"; public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key"; - public static final String PREF_CORRECTION_SETTINGS_KEY = "correction_settings"; - public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; - public static final String PREF_DEBUG_SETTINGS = "debug_settings"; - - public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; - public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction"; - - public static final String PREF_MISC_SETTINGS_KEY = "misc_settings"; - + public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; + public static final String PREF_MISC_SETTINGS = "misc_settings"; + public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; + public static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY = + "pref_suppress_language_switch_key"; + public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = + "pref_include_other_imes_in_language_switch_list"; public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY = "pref_key_preview_popup_dismiss_delay"; - public static final String PREF_KEY_USE_CONTACTS_DICT = - "pref_key_use_contacts_dict"; - public static final String PREF_KEY_ENABLE_SPAN_INSERT = - "enable_span_insert"; - - public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; - - public static final String PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS = + public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; + public static final String PREF_BIGRAM_SUGGESTION = "bigram_suggestion"; + public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction"; + public static final String PREF_KEY_ENABLE_SPAN_INSERT = "enable_span_insert"; + public static final String PREF_VIBRATION_DURATION_SETTINGS = "pref_vibration_duration_settings"; - public static final String PREF_KEYPRESS_SOUND_VOLUME = "pref_keypress_sound_volume"; - // Dialog ids - private static final int VOICE_INPUT_CONFIRM_DIALOG = 0; - - public static class Values { - // From resources: - public final int mDelayUpdateOldSuggestions; - public final String mWordSeparators; - public final String mMagicSpaceStrippers; - public final String mMagicSpaceSwappers; - public final String mSuggestPuncs; - public final SuggestedWords mSuggestPuncList; - private final String mSymbolsExcludedFromWordSeparators; - - // From preferences: - public final boolean mSoundOn; // Sound setting private to Latin IME (see mSilentModeOn) - public final boolean mVibrateOn; - public final boolean mKeyPreviewPopupOn; - public final int mKeyPreviewPopupDismissDelay; - public final boolean mAutoCap; - public final boolean mAutoCorrectEnabled; - public final double mAutoCorrectionThreshold; - // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary - public final boolean mBigramSuggestionEnabled; - // Prediction: use bigrams to predict the next word when there is no input for it yet - public final boolean mBigramPredictionEnabled; - public final boolean mUseContactsDict; - public final boolean mEnableSuggestionSpanInsertion; - - private final boolean mShowSettingsKey; - private final boolean mVoiceKeyEnabled; - private final boolean mVoiceKeyOnMain; - - public Values(final SharedPreferences prefs, final Context context, - final String localeStr) { - final Resources res = context.getResources(); - final Locale savedLocale; - if (null != localeStr) { - final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); - savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); - } else { - savedLocale = null; - } - - // Get the resources - mDelayUpdateOldSuggestions = res.getInteger( - R.integer.config_delay_update_old_suggestions); - mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols); - mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols); - String wordSeparators = mMagicSpaceStrippers + mMagicSpaceSwappers - + res.getString(R.string.magic_space_promoting_symbols); - final String symbolsExcludedFromWordSeparators = - res.getString(R.string.symbols_excluded_from_word_separators); - for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) { - wordSeparators = wordSeparators.replace( - symbolsExcludedFromWordSeparators.substring(i, i + 1), ""); - } - mSymbolsExcludedFromWordSeparators = symbolsExcludedFromWordSeparators; - mWordSeparators = wordSeparators; - mSuggestPuncs = res.getString(R.string.suggested_punctuations); - // TODO: it would be nice not to recreate this each time we change the configuration - mSuggestPuncList = createSuggestPuncList(mSuggestPuncs); - - // Get the settings preferences - final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator(); - mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON, - res.getBoolean(R.bool.config_default_vibration_enabled)); - mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, - res.getBoolean(R.bool.config_default_sound_enabled)); - mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res); - mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res); - mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); - mAutoCorrectEnabled = isAutoCorrectEnabled(prefs, res); - mBigramSuggestionEnabled = mAutoCorrectEnabled - && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled); - mBigramPredictionEnabled = mBigramSuggestionEnabled - && isBigramPredictionEnabled(prefs, res); - mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res); - mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); - mEnableSuggestionSpanInsertion = - prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true); - final boolean defaultShowSettingsKey = res.getBoolean( - R.bool.config_default_show_settings_key); - mShowSettingsKey = isShowSettingsKeyOption(res) - ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey) - : defaultShowSettingsKey; - final String voiceModeMain = res.getString(R.string.voice_mode_main); - final String voiceModeOff = res.getString(R.string.voice_mode_off); - final String voiceMode = prefs.getString(PREF_VOICE_SETTINGS_KEY, voiceModeMain); - mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff); - mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain); - - LocaleUtils.setSystemLocale(res, savedLocale); - } - - public boolean isSuggestedPunctuation(int code) { - return mSuggestPuncs.contains(String.valueOf((char)code)); - } - - public boolean isWordSeparator(int code) { - return mWordSeparators.contains(String.valueOf((char)code)); - } - - public boolean isSymbolExcludedFromWordSeparators(int code) { - return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code)); - } - - public boolean isMagicSpaceStripper(int code) { - return mMagicSpaceStrippers.contains(String.valueOf((char)code)); - } - - public boolean isMagicSpaceSwapper(int code) { - return mMagicSpaceSwappers.contains(String.valueOf((char)code)); - } - private static boolean isAutoCorrectEnabled(SharedPreferences sp, Resources resources) { - final String currentAutoCorrectionSetting = sp.getString( - Settings.PREF_AUTO_CORRECTION_THRESHOLD, - resources.getString(R.string.auto_correction_threshold_mode_index_modest)); - final String autoCorrectionOff = resources.getString( - R.string.auto_correction_threshold_mode_index_off); - return !currentAutoCorrectionSetting.equals(autoCorrectionOff); - } - - // Public to access from KeyboardSwitcher. Should it have access to some - // process-global instance instead? - public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) { - final boolean showPopupOption = resources.getBoolean( - R.bool.config_enable_show_popup_on_keypress_option); - if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview); - return sp.getBoolean(Settings.PREF_KEY_PREVIEW_POPUP_ON, - resources.getBoolean(R.bool.config_default_popup_preview)); - } - - // Likewise - public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp, - Resources resources) { - return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, - Integer.toString(resources.getInteger(R.integer.config_delay_after_preview)))); - } - - private static boolean isBigramSuggestionEnabled(SharedPreferences sp, Resources resources, - boolean autoCorrectEnabled) { - final boolean showBigramSuggestionsOption = resources.getBoolean( - R.bool.config_enable_bigram_suggestions_option); - if (!showBigramSuggestionsOption) { - return autoCorrectEnabled; - } - return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, resources.getBoolean( - R.bool.config_default_bigram_suggestions)); - } - - private static boolean isBigramPredictionEnabled(SharedPreferences sp, - Resources resources) { - return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean( - R.bool.config_default_bigram_prediction)); - } - - private static double getAutoCorrectionThreshold(SharedPreferences sp, - Resources resources) { - final String currentAutoCorrectionSetting = sp.getString( - Settings.PREF_AUTO_CORRECTION_THRESHOLD, - resources.getString(R.string.auto_correction_threshold_mode_index_modest)); - final String[] autoCorrectionThresholdValues = resources.getStringArray( - R.array.auto_correction_threshold_values); - // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off. - double autoCorrectionThreshold = Double.MAX_VALUE; - try { - final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting); - if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) { - autoCorrectionThreshold = Double.parseDouble( - autoCorrectionThresholdValues[arrayIndex]); - } - } catch (NumberFormatException e) { - // Whenever the threshold settings are correct, never come here. - autoCorrectionThreshold = Double.MAX_VALUE; - Log.w(TAG, "Cannot load auto correction threshold setting." - + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting - + ", autoCorrectionThresholdValues: " - + Arrays.toString(autoCorrectionThresholdValues)); - } - return autoCorrectionThreshold; - } - - private static SuggestedWords createSuggestPuncList(final String puncs) { - SuggestedWords.Builder builder = new SuggestedWords.Builder(); - if (puncs != null) { - for (int i = 0; i < puncs.length(); i++) { - builder.addWord(puncs.subSequence(i, i + 1)); - } - } - return builder.setIsPunctuationSuggestions().build(); - } - - public static boolean isShowSettingsKeyOption(final Resources resources) { - return resources.getBoolean(R.bool.config_enable_show_settings_key_option); - - } - - public boolean isSettingsKeyEnabled() { - return mShowSettingsKey; - } - - public boolean isVoiceKeyEnabled(EditorInfo attribute) { - final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); - final int inputType = (attribute != null) ? attribute.inputType : 0; - return shortcutImeEnabled && mVoiceKeyEnabled - && !InputTypeCompatUtils.isPasswordInputType(inputType); - } + public static final String PREF_INPUT_LANGUAGE = "input_language"; + public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; + public static final String PREF_DEBUG_SETTINGS = "debug_settings"; - public boolean isVoiceKeyOnMain() { - return mVoiceKeyOnMain; - } - } + // Dialog ids + private static final int VOICE_INPUT_CONFIRM_DIALOG = 0; private PreferenceScreen mInputLanguageSelection; private PreferenceScreen mKeypressVibrationDurationSettingsPref; private PreferenceScreen mKeypressSoundVolumeSettingsPref; private ListPreference mVoicePreference; - private CheckBoxPreference mShowSettingsKeyPreference; private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThresholdPreference; private ListPreference mKeyPreviewPopupDismissDelay; @@ -363,22 +145,21 @@ public class Settings extends InputMethodSettingsActivity final Context context = getActivityInternal(); addPreferencesFromResource(R.xml.prefs); - mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES); + mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES_SETTINGS); mInputLanguageSelection.setOnPreferenceClickListener(this); - mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY); - mShowSettingsKeyPreference = (CheckBoxPreference) findPreference(PREF_SHOW_SETTINGS_KEY); + mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE); mShowCorrectionSuggestionsPreference = (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING); SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); mVoiceModeOff = getString(R.string.voice_mode_off); - mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff) + mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff) .equals(mVoiceModeOff)); mAutoCorrectionThresholdPreference = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD); - mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS); + mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTION); mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS); mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); if (mDebugSettingsPreference != null) { @@ -391,15 +172,11 @@ public class Settings extends InputMethodSettingsActivity ensureConsistencyOfAutoCorrectionSettings(); final PreferenceGroup generalSettings = - (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY); + (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS); final PreferenceGroup textCorrectionGroup = - (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY); + (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS); final PreferenceGroup miscSettings = - (PreferenceGroup) findPreference(PREF_MISC_SETTINGS_KEY); - - if (!Values.isShowSettingsKeyOption(res)) { - generalSettings.removePreference(mShowSettingsKeyPreference); - } + (PreferenceGroup) findPreference(PREF_MISC_SETTINGS); final boolean showVoiceKeyOption = res.getBoolean( R.bool.config_enable_show_voice_key_option); @@ -412,13 +189,13 @@ public class Settings extends InputMethodSettingsActivity } if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { - generalSettings.removePreference(findPreference(PREF_SUBTYPES)); + generalSettings.removePreference(findPreference(PREF_SUBTYPES_SETTINGS)); } final boolean showPopupOption = res.getBoolean( R.bool.config_enable_show_popup_on_keypress_option); if (!showPopupOption) { - generalSettings.removePreference(findPreference(PREF_KEY_PREVIEW_POPUP_ON)); + generalSettings.removePreference(findPreference(PREF_POPUP_ON)); } final boolean showBigramSuggestionsOption = res.getBoolean( @@ -430,6 +207,11 @@ public class Settings extends InputMethodSettingsActivity } } + final CheckBoxPreference includeOtherImesInLanguageSwitchList = + (CheckBoxPreference)findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST); + includeOtherImesInLanguageSwitchList.setEnabled( + !SettingsValues.isLanguageSwitchKeySupressed(prefs)); + mKeyPreviewPopupDismissDelay = (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); final String[] entries = new String[] { @@ -437,14 +219,15 @@ public class Settings extends InputMethodSettingsActivity res.getString(R.string.key_preview_popup_dismiss_default_delay), }; final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger( - R.integer.config_delay_after_preview)); + R.integer.config_key_preview_linger_timeout)); mKeyPreviewPopupDismissDelay.setEntries(entries); mKeyPreviewPopupDismissDelay.setEntryValues( new String[] { "0", popupDismissDelayDefaultValue }); if (null == mKeyPreviewPopupDismissDelay.getValue()) { mKeyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue); } - mKeyPreviewPopupDismissDelay.setEnabled(Values.isKeyPreviewPopupEnabled(prefs, res)); + mKeyPreviewPopupDismissDelay.setEnabled( + SettingsValues.isKeyPreviewPopupEnabled(prefs, res)); final PreferenceScreen dictionaryLink = (PreferenceScreen) findPreference(PREF_CONFIGURE_DICTIONARIES_KEY); @@ -455,17 +238,26 @@ public class Settings extends InputMethodSettingsActivity textCorrectionGroup.removePreference(dictionaryLink); } - final boolean showUsabilityModeStudyOption = res.getBoolean( - R.bool.config_enable_usability_study_mode_option); - if (!showUsabilityModeStudyOption || !ENABLE_EXPERIMENTAL_SETTINGS) { - final Preference pref = findPreference(PREF_USABILITY_STUDY_MODE); - if (pref != null) { - miscSettings.removePreference(pref); + final boolean isResearcherPackage = LatinImeLogger.isResearcherPackage(this); + final boolean showUsabilityStudyModeOption = + res.getBoolean(R.bool.config_enable_usability_study_mode_option) + || isResearcherPackage || ENABLE_EXPERIMENTAL_SETTINGS; + final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); + if (!showUsabilityStudyModeOption) { + if (usabilityStudyPref != null) { + miscSettings.removePreference(usabilityStudyPref); + } + } + if (isResearcherPackage) { + if (usabilityStudyPref instanceof CheckBoxPreference) { + CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; + checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, true)); + checkbox.setSummary(R.string.settings_warning_researcher_mode); } } mKeypressVibrationDurationSettingsPref = - (PreferenceScreen) findPreference(PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS); + (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS); if (mKeypressVibrationDurationSettingsPref != null) { mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener( new OnPreferenceClickListener() { @@ -521,20 +313,26 @@ public class Settings extends InputMethodSettingsActivity public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { (new BackupManager(getActivityInternal())).dataChanged(); // If turning on voice input, show dialog - if (key.equals(PREF_VOICE_SETTINGS_KEY) && !mVoiceOn) { - if (!prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff) + if (key.equals(PREF_VOICE_MODE) && !mVoiceOn) { + if (!prefs.getString(PREF_VOICE_MODE, mVoiceModeOff) .equals(mVoiceModeOff)) { showVoiceConfirmation(); } - } else if (key.equals(PREF_KEY_PREVIEW_POPUP_ON)) { + } else if (key.equals(PREF_POPUP_ON)) { final ListPreference popupDismissDelay = (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); if (null != popupDismissDelay) { - popupDismissDelay.setEnabled(prefs.getBoolean(PREF_KEY_PREVIEW_POPUP_ON, true)); + popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true)); } + } else if (key.equals(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) { + final CheckBoxPreference includeOtherImesInLanguageSwicthList = + (CheckBoxPreference)findPreference( + PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST); + includeOtherImesInLanguageSwicthList.setEnabled( + !SettingsValues.isLanguageSwitchKeySupressed(prefs)); } ensureConsistencyOfAutoCorrectionSettings(); - mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff) + mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff) .equals(mVoiceModeOff)); updateVoiceModeSummary(); updateShowCorrectionSuggestionsSummary(); @@ -545,10 +343,9 @@ public class Settings extends InputMethodSettingsActivity @Override public boolean onPreferenceClick(Preference pref) { if (pref == mInputLanguageSelection) { - startActivity(CompatUtils.getInputLanguageSelectionIntent( - Utils.getInputMethodId( - InputMethodManagerCompatWrapper.getInstance(), - getActivityInternal().getApplicationInfo().packageName), 0)); + final String imeId = SubtypeUtils.getInputMethodId( + getActivityInternal().getApplicationInfo().packageName); + startActivity(CompatUtils.getInputLanguageSelectionIntent(imeId, 0)); return true; } return false; @@ -660,7 +457,7 @@ public class Settings extends InputMethodSettingsActivity SharedPreferences sp, Resources res) { if (mKeypressVibrationDurationSettingsPref != null) { mKeypressVibrationDurationSettingsPref.setSummary( - Utils.getCurrentVibrationDuration(sp, res) + SettingsValues.getCurrentVibrationDuration(sp, res) + res.getString(R.string.settings_ms)); } } @@ -676,7 +473,7 @@ public class Settings extends InputMethodSettingsActivity public void onClick(DialogInterface dialog, int whichButton) { final int ms = Integer.valueOf( mKeypressVibrationDurationSettingsTextView.getText().toString()); - sp.edit().putInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, ms).apply(); + sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply(); updateKeypressVibrationDurationSettingsSummary(sp, res); } }); @@ -688,7 +485,7 @@ public class Settings extends InputMethodSettingsActivity }); final View v = context.getLayoutInflater().inflate( R.layout.vibration_settings_dialog, null); - final int currentMs = Utils.getCurrentVibrationDuration( + final int currentMs = SettingsValues.getCurrentVibrationDuration( getPreferenceManager().getSharedPreferences(), getResources()); mKeypressVibrationDurationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value); final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings); @@ -717,8 +514,8 @@ public class Settings extends InputMethodSettingsActivity private void updateKeypressSoundVolumeSummary(SharedPreferences sp, Resources res) { if (mKeypressSoundVolumeSettingsPref != null) { - mKeypressSoundVolumeSettingsPref.setSummary( - String.valueOf((int)(Utils.getCurrentKeypressSoundVolume(sp, res) * 100))); + mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf( + (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100))); } } @@ -747,8 +544,8 @@ public class Settings extends InputMethodSettingsActivity }); final View v = context.getLayoutInflater().inflate( R.layout.sound_effect_volume_dialog, null); - final int currentVolumeInt = (int)(Utils.getCurrentKeypressSoundVolume( - getPreferenceManager().getSharedPreferences(), getResources()) * 100); + final int currentVolumeInt = + (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100); mKeypressSoundVolumeSettingsTextView = (TextView)v.findViewById(R.id.sound_effect_volume_value); final SeekBar sb = (SeekBar)v.findViewById(R.id.sound_effect_volume_bar); @@ -774,4 +571,4 @@ public class Settings extends InputMethodSettingsActivity builder.setView(v); builder.create().show(); } -}
\ No newline at end of file +} diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java new file mode 100644 index 000000000..4346a3671 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2011 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 android.content.SharedPreferences; +import android.content.res.Resources; +import android.os.Build; +import android.util.Log; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; +import com.android.inputmethod.compat.InputTypeCompatUtils; +import com.android.inputmethod.compat.VibratorCompatWrapper; +import com.android.inputmethod.keyboard.internal.KeySpecParser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +public class SettingsValues { + private static final String TAG = SettingsValues.class.getSimpleName(); + + // From resources: + public final int mDelayUpdateOldSuggestions; + public final String mWeakSpaceStrippers; + public final String mWeakSpaceSwappers; + private final String mPhantomSpacePromotingSymbols; + public final SuggestedWords mSuggestPuncList; + private final String mSymbolsExcludedFromWordSeparators; + public final String mWordSeparators; + public final CharSequence mHintToSaveText; + + // From preferences, in the same order as xml/prefs.xml: + public final boolean mAutoCap; + public final boolean mVibrateOn; + public final boolean mSoundOn; + public final boolean mKeyPreviewPopupOn; + private final String mVoiceMode; + private final String mAutoCorrectionThresholdRawValue; + public final String mShowSuggestionsSetting; + @SuppressWarnings("unused") // TODO: Use this + private final boolean mUsabilityStudyMode; + public final boolean mIncludesOtherImesInLanguageSwitchList; + public final boolean mIsLanguageSwitchKeySuppressed; + @SuppressWarnings("unused") // TODO: Use this + private final String mKeyPreviewPopupDismissDelayRawValue; + public final boolean mUseContactsDict; + // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary + public final boolean mBigramSuggestionEnabled; + // Prediction: use bigrams to predict the next word when there is no input for it yet + public final boolean mBigramPredictionEnabled; + public final boolean mEnableSuggestionSpanInsertion; + @SuppressWarnings("unused") // TODO: Use this + private final int mVibrationDurationSettingsRawValue; + @SuppressWarnings("unused") // TODO: Use this + private final float mKeypressSoundVolumeRawValue; + + // Deduced settings + public final int mKeypressVibrationDuration; + public final float mFxVolume; + public final int mKeyPreviewPopupDismissDelay; + public final boolean mAutoCorrectEnabled; + public final double mAutoCorrectionThreshold; + private final boolean mVoiceKeyEnabled; + private final boolean mVoiceKeyOnMain; + + public SettingsValues(final SharedPreferences prefs, final Context context, + final String localeStr) { + final Resources res = context.getResources(); + final Locale savedLocale; + if (null != localeStr) { + final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); + savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); + } else { + savedLocale = null; + } + + // Get the resources + mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions); + mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols); + mWeakSpaceSwappers = res.getString(R.string.weak_space_swapping_symbols); + mPhantomSpacePromotingSymbols = res.getString(R.string.phantom_space_promoting_symbols); + if (LatinImeLogger.sDBG) { + final int length = mWeakSpaceStrippers.length(); + for (int i = 0; i < length; i = mWeakSpaceStrippers.offsetByCodePoints(i, 1)) { + if (isWeakSpaceSwapper(mWeakSpaceStrippers.codePointAt(i))) { + throw new RuntimeException("Char code " + mWeakSpaceStrippers.codePointAt(i) + + " is both a weak space swapper and stripper."); + } + } + } + final String[] suggestPuncsSpec = KeySpecParser.parseCsvString( + res.getString(R.string.suggested_punctuations), res, R.string.english_ime_name); + mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); + mSymbolsExcludedFromWordSeparators = + res.getString(R.string.symbols_excluded_from_word_separators); + mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers, + mSymbolsExcludedFromWordSeparators, res); + mHintToSaveText = context.getText(R.string.hint_add_to_dictionary); + + // Get the settings preferences + mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true); + mVibrateOn = isVibrateOn(context, prefs, res); + mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON, + res.getBoolean(R.bool.config_default_sound_enabled)); + mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res); + final String voiceModeMain = res.getString(R.string.voice_mode_main); + final String voiceModeOff = res.getString(R.string.voice_mode_off); + mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain); + mAutoCorrectionThresholdRawValue = prefs.getString(Settings.PREF_AUTO_CORRECTION_THRESHOLD, + res.getString(R.string.auto_correction_threshold_mode_index_modest)); + mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING, + res.getString(R.string.prefs_suggestion_visibility_default_value)); + mUsabilityStudyMode = getUsabilityStudyMode(prefs); + mIncludesOtherImesInLanguageSwitchList = prefs.getBoolean( + Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false); + mIsLanguageSwitchKeySuppressed = isLanguageSwitchKeySupressed(prefs); + mKeyPreviewPopupDismissDelayRawValue = prefs.getString( + Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, + Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout))); + mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); + mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue); + mBigramSuggestionEnabled = mAutoCorrectEnabled + && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled); + mBigramPredictionEnabled = mBigramSuggestionEnabled + && isBigramPredictionEnabled(prefs, res); + mEnableSuggestionSpanInsertion = + prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true); + mVibrationDurationSettingsRawValue = + prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1); + mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f); + + // Compute other readable settings + mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res); + mFxVolume = getCurrentKeypressSoundVolume(prefs, res); + mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res); + mAutoCorrectionThreshold = getAutoCorrectionThreshold(res, + mAutoCorrectionThresholdRawValue); + mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff); + mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain); + + LocaleUtils.setSystemLocale(res, savedLocale); + } + + // Helper functions to create member values. + private static SuggestedWords createSuggestPuncList(final String[] puncs) { + final ArrayList<SuggestedWords.SuggestedWordInfo> puncList = + new ArrayList<SuggestedWords.SuggestedWordInfo>(); + if (puncs != null) { + for (final String puncSpec : puncs) { + puncList.add(new SuggestedWords.SuggestedWordInfo( + KeySpecParser.getLabel(puncSpec))); + } + } + return new SuggestedWords(puncList, + false /* typedWordValid */, + false /* hasAutoCorrectionCandidate */, + false /* allowsToBeAutoCorrected */, + true /* isPunctuationSuggestions */, + false /* isObsoleteSuggestions */); + } + + private static String createWordSeparators(final String weakSpaceStrippers, + final String weakSpaceSwappers, final String symbolsExcludedFromWordSeparators, + final Resources res) { + String wordSeparators = weakSpaceStrippers + weakSpaceSwappers + + res.getString(R.string.phantom_space_promoting_symbols); + for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) { + wordSeparators = wordSeparators.replace( + symbolsExcludedFromWordSeparators.substring(i, i + 1), ""); + } + return wordSeparators; + } + + private static boolean isVibrateOn(final Context context, final SharedPreferences prefs, + final Resources res) { + final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator(); + return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON, + res.getBoolean(R.bool.config_default_vibration_enabled)); + } + + public boolean isWordSeparator(int code) { + return mWordSeparators.contains(String.valueOf((char)code)); + } + + public boolean isSymbolExcludedFromWordSeparators(int code) { + return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code)); + } + + public boolean isWeakSpaceStripper(int code) { + // TODO: this does not work if the code does not fit in a char + return mWeakSpaceStrippers.contains(String.valueOf((char)code)); + } + + public boolean isWeakSpaceSwapper(int code) { + // TODO: this does not work if the code does not fit in a char + return mWeakSpaceSwappers.contains(String.valueOf((char)code)); + } + + public boolean isPhantomSpacePromotingSymbol(int code) { + // TODO: this does not work if the code does not fit in a char + return mPhantomSpacePromotingSymbols.contains(String.valueOf((char)code)); + } + + private static boolean isAutoCorrectEnabled(final Resources resources, + final String currentAutoCorrectionSetting) { + final String autoCorrectionOff = resources.getString( + R.string.auto_correction_threshold_mode_index_off); + return !currentAutoCorrectionSetting.equals(autoCorrectionOff); + } + + // Public to access from KeyboardSwitcher. Should it have access to some + // process-global instance instead? + public static boolean isKeyPreviewPopupEnabled(SharedPreferences sp, Resources resources) { + final boolean showPopupOption = resources.getBoolean( + R.bool.config_enable_show_popup_on_keypress_option); + if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview); + return sp.getBoolean(Settings.PREF_POPUP_ON, + resources.getBoolean(R.bool.config_default_popup_preview)); + } + + // Likewise + public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp, + Resources resources) { + // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here. + return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, + Integer.toString(resources.getInteger( + R.integer.config_key_preview_linger_timeout)))); + } + + private static boolean isBigramSuggestionEnabled(final SharedPreferences sp, + final Resources resources, final boolean autoCorrectEnabled) { + final boolean showBigramSuggestionsOption = resources.getBoolean( + R.bool.config_enable_bigram_suggestions_option); + if (!showBigramSuggestionsOption) { + return autoCorrectEnabled; + } + return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTION, resources.getBoolean( + R.bool.config_default_bigram_suggestions)); + } + + private static boolean isBigramPredictionEnabled(final SharedPreferences sp, + final Resources resources) { + return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean( + R.bool.config_default_bigram_prediction)); + } + + private static double getAutoCorrectionThreshold(final Resources resources, + final String currentAutoCorrectionSetting) { + final String[] autoCorrectionThresholdValues = resources.getStringArray( + R.array.auto_correction_threshold_values); + // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off. + double autoCorrectionThreshold = Double.MAX_VALUE; + try { + final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting); + if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) { + autoCorrectionThreshold = Double.parseDouble( + autoCorrectionThresholdValues[arrayIndex]); + } + } catch (NumberFormatException e) { + // Whenever the threshold settings are correct, never come here. + autoCorrectionThreshold = Double.MAX_VALUE; + Log.w(TAG, "Cannot load auto correction threshold setting." + + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting + + ", autoCorrectionThresholdValues: " + + Arrays.toString(autoCorrectionThresholdValues)); + } + return autoCorrectionThreshold; + } + + public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) { + final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); + final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; + return shortcutImeEnabled && mVoiceKeyEnabled + && !InputTypeCompatUtils.isPasswordInputType(inputType); + } + + public boolean isVoiceKeyOnMain() { + return mVoiceKeyOnMain; + } + + public static boolean isLanguageSwitchKeySupressed(SharedPreferences sp) { + return sp.getBoolean(Settings.PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false); + } + + public boolean isLanguageSwitchKeyEnabled(Context context) { + if (mIsLanguageSwitchKeySuppressed) { + return false; + } + if (mIncludesOtherImesInLanguageSwitchList) { + return SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(/* include aux subtypes */false); + } else { + return SubtypeUtils.hasMultipleEnabledSubtypesInThisIme( + context, /* include aux subtypes */false); + } + } + + public boolean isFullscreenModeAllowed(Resources res) { + return res.getBoolean(R.bool.config_use_fullscreen_mode); + } + + // Accessed from the settings interface, hence public + public static float getCurrentKeypressSoundVolume(final SharedPreferences sp, + final Resources res) { + // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here + final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f); + if (volume >= 0) { + return volume; + } + + final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes); + final String hardwarePrefix = Build.HARDWARE + ","; + for (final String element : volumePerHardwareList) { + if (element.startsWith(hardwarePrefix)) { + return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1)); + } + } + return -1.0f; + } + + // Likewise + public static int getCurrentVibrationDuration(final SharedPreferences sp, + final Resources res) { + // TODO: use mKeypressVibrationDuration instead of reading it again here + final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1); + if (ms >= 0) { + return ms; + } + final String[] durationPerHardwareList = res.getStringArray( + R.array.keypress_vibration_durations); + final String hardwarePrefix = Build.HARDWARE + ","; + for (final String element : durationPerHardwareList) { + if (element.startsWith(hardwarePrefix)) { + return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1)); + } + } + return -1; + } + + // Likewise + public static boolean getUsabilityStudyMode(final SharedPreferences prefs) { + // TODO: use mUsabilityStudyMode instead of reading it again here + return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true); + } +} diff --git a/java/src/com/android/inputmethod/latin/StringBuilderPool.java b/java/src/com/android/inputmethod/latin/StringBuilderPool.java deleted file mode 100644 index a663ed43e..000000000 --- a/java/src/com/android/inputmethod/latin/StringBuilderPool.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 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 java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A pool of string builders to be used from anywhere. - */ -public class StringBuilderPool { - // Singleton - private static final StringBuilderPool sInstance = new StringBuilderPool(); - private static final boolean DEBUG = false; - private StringBuilderPool() {} - // TODO: Make this a normal array with a size of 20, or a ConcurrentQueue - private final List<StringBuilder> mPool = - Collections.synchronizedList(new ArrayList<StringBuilder>()); - - public static StringBuilder getStringBuilder(final int initialSize) { - // TODO: although the pool is synchronized, the following is not thread-safe. - // Two threads entering this at the same time could take the same size of the pool and the - // second to attempt removing this index from the pool would crash with an - // IndexOutOfBoundsException. - // At the moment this pool is only used in Suggest.java and only in one thread so it's - // okay. The simplest thing to do here is probably to replace the ArrayList with a - // ConcurrentQueue. - final int poolSize = sInstance.mPool.size(); - final StringBuilder sb = poolSize > 0 ? (StringBuilder) sInstance.mPool.remove(poolSize - 1) - : new StringBuilder(initialSize); - sb.setLength(0); - return sb; - } - - public static void recycle(final StringBuilder garbage) { - if (DEBUG) { - final int gid = garbage.hashCode(); - for (final StringBuilder q : sInstance.mPool) { - if (gid == q.hashCode()) throw new RuntimeException("Duplicate id " + gid); - } - } - sInstance.mPool.add(garbage); - } - - public static void ensureCapacity(final int capacity, final int initialSize) { - for (int i = sInstance.mPool.size(); i < capacity; ++i) { - final StringBuilder sb = new StringBuilder(initialSize); - sInstance.mPool.add(sb); - } - } - - public static int getSize() { - return sInstance.mPool.size(); - } -} diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java new file mode 100644 index 000000000..7b34cae63 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/StringUtils.java @@ -0,0 +1,190 @@ +/* + * 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.text.TextUtils; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.Keyboard; + +import java.util.ArrayList; +import java.util.Locale; + +public class StringUtils { + private StringUtils() { + // This utility class is not publicly instantiable. + } + + public static boolean canBeFollowedByPeriod(final int codePoint) { + // TODO: Check again whether there really ain't a better way to check this. + // TODO: This should probably be language-dependant... + return Character.isLetterOrDigit(codePoint) + || codePoint == Keyboard.CODE_SINGLE_QUOTE + || codePoint == Keyboard.CODE_DOUBLE_QUOTE + || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS + || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET + || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET + || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; + } + + public static int codePointCount(String text) { + if (TextUtils.isEmpty(text)) return 0; + return text.codePointCount(0, text.length()); + } + + public static boolean containsInCsv(String key, String csv) { + if (csv == null) + return false; + for (String option : csv.split(",")) { + if (option.equals(key)) + return true; + } + return false; + } + + public static boolean inPrivateImeOptions(String packageName, String key, + EditorInfo editorInfo) { + if (editorInfo == null) + return false; + return containsInCsv(packageName != null ? packageName + "." + key : key, + editorInfo.privateImeOptions); + } + + /** + * Returns true if a and b are equal ignoring the case of the character. + * @param a first character to check + * @param b second character to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(char a, char b) { + // Some language, such as Turkish, need testing both cases. + return a == b + || Character.toLowerCase(a) == Character.toLowerCase(b) + || Character.toUpperCase(a) == Character.toUpperCase(b); + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if they are + * both null. + * @param a first CharSequence to check + * @param b second CharSequence to check + * @return {@code true} if a and b are equal, {@code false} otherwise. + */ + public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { + if (a == b) + return true; // including both a and b are null. + if (a == null || b == null) + return false; + final int length = a.length(); + if (length != b.length()) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) + return false; + } + return true; + } + + /** + * Returns true if a and b are equal ignoring the case of the characters, including if a is null + * and b is zero length. + * @param a CharSequence to check + * @param b character array to check + * @param offset start offset of array b + * @param length length of characters in array b + * @return {@code true} if a and b are equal, {@code false} otherwise. + * @throws IndexOutOfBoundsException + * if {@code offset < 0 || length < 0 || offset + length > data.length}. + * @throws NullPointerException if {@code b == null}. + */ + public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { + if (offset < 0 || length < 0 || length > b.length - offset) + throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset + + " length=" + length); + if (a == null) + return length == 0; // including a is null and b is zero length. + if (a.length() != length) + return false; + for (int i = 0; i < length; i++) { + if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) + return false; + } + return true; + } + + /** + * Remove duplicates from an array of strings. + * + * This method will always keep the first occurence of all strings at their position + * in the array, removing the subsequent ones. + */ + public static void removeDupes(final ArrayList<CharSequence> suggestions) { + if (suggestions.size() < 2) return; + int i = 1; + // Don't cache suggestions.size(), since we may be removing items + while (i < suggestions.size()) { + final CharSequence cur = suggestions.get(i); + // Compare each suggestion with each previous suggestion + for (int j = 0; j < i; j++) { + CharSequence previous = suggestions.get(j); + if (TextUtils.equals(cur, previous)) { + suggestions.remove(i); + i--; + break; + } + } + i++; + } + } + + public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { + if (returnsNameInThisLocale) { + return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); + } else { + return toTitleCase(locale.getDisplayName(), locale); + } + } + + public static String getDisplayLanguage(Locale locale) { + return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); + } + + public static String getMiddleDisplayLanguage(Locale locale) { + return toTitleCase((LocaleUtils.constructLocaleFromString( + locale.getLanguage()).getDisplayLanguage(locale)), locale); + } + + public static String getShortDisplayLanguage(Locale locale) { + return toTitleCase(locale.getLanguage(), locale); + } + + public static String toTitleCase(String s, Locale locale) { + if (s.length() <= 1) { + // TODO: is this really correct? Shouldn't this be s.toUpperCase()? + return s; + } + // TODO: fix the bugs below + // - This does not work for Greek, because it returns upper case instead of title case. + // - It does not work for Serbian, because it fails to account for the "lj" character, + // which should be "Lj" in title case and "LJ" in upper case. + // - It does not work for Dutch, because it fails to account for the "ij" digraph, which + // are two different characters but both should be capitalized as "IJ" as if they were + // a single letter. + // - It also does not work with unicode surrogate code points. + return s.toUpperCase(locale).charAt(0) + s.substring(1); + } +} diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 8a4862094..ffbbf9bb8 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -35,7 +35,6 @@ import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.LatinKeyboard; import java.util.ArrayList; import java.util.Arrays; @@ -47,8 +46,8 @@ public class SubtypeSwitcher { private static boolean DBG = LatinImeLogger.sDBG; private static final String TAG = SubtypeSwitcher.class.getSimpleName(); + public static final String KEYBOARD_MODE = "keyboard"; private static final char LOCALE_SEPARATER = '_'; - private static final String KEYBOARD_MODE = "keyboard"; private static final String VOICE_MODE = "voice"; private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; @@ -421,11 +420,7 @@ public class SubtypeSwitcher { ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); mIsNetworkConnected = !noConnection; - final KeyboardSwitcher switcher = KeyboardSwitcher.getInstance(); - final LatinKeyboard keyboard = switcher.getLatinKeyboard(); - if (keyboard != null) { - keyboard.updateShortcutKey(isShortcutImeReady(), switcher.getKeyboardView()); - } + KeyboardSwitcher.getInstance().onNetworkStateChanged(); } ////////////////////////////////// @@ -517,7 +512,7 @@ public class SubtypeSwitcher { } public String getInputLanguageName() { - return Utils.getDisplayLanguage(getInputLocale()); + return StringUtils.getDisplayLanguage(getInputLocale()); } ///////////////////////////// diff --git a/java/src/com/android/inputmethod/latin/SubtypeUtils.java b/java/src/com/android/inputmethod/latin/SubtypeUtils.java new file mode 100644 index 000000000..cb2bcf43f --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SubtypeUtils.java @@ -0,0 +1,135 @@ +/* + * 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.compat.InputMethodInfoCompatWrapper; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; + +import java.util.Collections; +import java.util.List; + +public class SubtypeUtils { + private SubtypeUtils() { + // This utility class is not publicly instantiable. + } + + // TODO: Cache my InputMethodInfo and/or InputMethodSubtype list. + public static boolean checkIfSubtypeBelongsToThisIme(Context context, + InputMethodSubtypeCompatWrapper ims) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final InputMethodInfoCompatWrapper myImi = getInputMethodInfo(context.getPackageName()); + final List<InputMethodSubtypeCompatWrapper> subtypes = + imm.getEnabledInputMethodSubtypeList(myImi, true); + for (final InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (subtype.equals(ims)) { + return true; + } + } + return false; + } + + public static boolean hasMultipleEnabledIMEsOrSubtypes( + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList(); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); + } + + public static boolean hasMultipleEnabledSubtypesInThisIme(Context context, + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodInfoCompatWrapper myImi = getInputMethodInfo(context.getPackageName()); + final List<InputMethodInfoCompatWrapper> imiList = Collections.singletonList(myImi); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); + } + + private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, + List<InputMethodInfoCompatWrapper> imiList) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + // Number of the filtered IMEs + int filteredImisCount = 0; + + for (InputMethodInfoCompatWrapper imi : imiList) { + // We can return true immediately after we find two or more filtered IMEs. + if (filteredImisCount > 1) return true; + final List<InputMethodSubtypeCompatWrapper> subtypes = + imm.getEnabledInputMethodSubtypeList(imi, true); + // IMEs that have no subtypes should be counted. + if (subtypes.isEmpty()) { + ++filteredImisCount; + continue; + } + + int auxCount = 0; + for (InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (subtype.isAuxiliary()) { + ++auxCount; + } + } + final int nonAuxCount = subtypes.size() - auxCount; + + // IMEs that have one or more non-auxiliary subtypes should be counted. + // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary + // subtypes should be counted as well. + if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { + ++filteredImisCount; + continue; + } + } + + if (filteredImisCount > 1) { + return true; + } + final List<InputMethodSubtypeCompatWrapper> subtypes = + imm.getEnabledInputMethodSubtypeList(null, true); + int keyboardCount = 0; + // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's + // both explicitly and implicitly enabled input method subtype. + // (The current IME should be LatinIME.) + for (InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (SubtypeSwitcher.KEYBOARD_MODE.equals(subtype.getMode())) { + ++keyboardCount; + } + } + return keyboardCount > 1; + } + + public static String getInputMethodId(String packageName) { + return getInputMethodInfo(packageName).getId(); + } + + public static InputMethodInfoCompatWrapper getInputMethodInfo(String packageName) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) { + throw new RuntimeException("Input method manager not found"); + } + + for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) { + if (imi.getPackageName().equals(packageName)) + return imi; + } + throw new RuntimeException("Can not find input method id for " + packageName); + } +} diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index caa5aac51..69754d769 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -20,7 +20,9 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.io.File; import java.util.ArrayList; @@ -42,9 +44,8 @@ public class Suggest implements Dictionary.WordCallback { public static final int APPROX_MAX_WORD_LENGTH = 32; public static final int CORRECTION_NONE = 0; - public static final int CORRECTION_BASIC = 1; - public static final int CORRECTION_FULL = 2; - public static final int CORRECTION_FULL_BIGRAM = 3; + public static final int CORRECTION_FULL = 1; + public static final int CORRECTION_FULL_BIGRAM = 2; /** * Words that appear in both bigram and unigram data gets multiplier ranging from @@ -83,8 +84,6 @@ public class Suggest implements Dictionary.WordCallback { private static final boolean DBG = LatinImeLogger.sDBG; - private AutoCorrection mAutoCorrection; - private Dictionary mMainDict; private ContactsDictionary mContactsDict; private WhitelistDictionary mWhiteListDictionary; @@ -100,14 +99,15 @@ public class Suggest implements Dictionary.WordCallback { private int[] mBigramScores = new int[PREF_MAX_BIGRAMS]; private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>(); - ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); - private CharSequence mTypedWord; + private ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); + private CharSequence mConsideredWord; // TODO: Remove these member variables by passing more context to addWord() callback method private boolean mIsFirstCharCapitalized; private boolean mIsAllUpperCase; + private int mTrailingSingleQuotesCount; - private int mCorrectionMode = CORRECTION_BASIC; + private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; public Suggest(final Context context, final int dictionaryResId, final Locale locale) { initAsynchronously(context, dictionaryResId, locale); @@ -116,15 +116,13 @@ public class Suggest implements Dictionary.WordCallback { /* package for test */ Suggest(final Context context, final File dictionary, final long startOffset, final long length, final Flag[] flagArray, final Locale locale) { - initSynchronously(null, DictionaryFactory.createDictionaryForTest(context, dictionary, + initSynchronously(context, DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset, length, flagArray), locale); } private void initWhitelistAndAutocorrectAndPool(final Context context, final Locale locale) { mWhiteListDictionary = new WhitelistDictionary(context, locale); addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); - mAutoCorrection = new AutoCorrection(); - StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength()); } private void initAsynchronously(final Context context, final int dictionaryResId, @@ -144,7 +142,7 @@ public class Suggest implements Dictionary.WordCallback { initWhitelistAndAutocorrectAndPool(context, locale); } - private void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key, + private static void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key, Dictionary dict) { final Dictionary oldDict = (dict == null) ? dictionaries.remove(key) @@ -169,14 +167,6 @@ public class Suggest implements Dictionary.WordCallback { }.start(); } - public int getCorrectionMode() { - return mCorrectionMode; - } - - public void setCorrectionMode(int mode) { - mCorrectionMode = mode; - } - // The main dictionary could have been loaded asynchronously. Don't cache the return value // of this method. public boolean hasMainDictionary() { @@ -191,7 +181,7 @@ public class Suggest implements Dictionary.WordCallback { return mUnigramDictionaries; } - public int getApproxMaxWordLength() { + public static int getApproxMaxWordLength() { return APPROX_MAX_WORD_LENGTH; } @@ -226,44 +216,11 @@ public class Suggest implements Dictionary.WordCallback { mAutoCorrectionThreshold = threshold; } - public boolean isAggressiveAutoCorrectionMode() { - return (mAutoCorrectionThreshold == 0); - } - - /** - * Number of suggestions to generate from the input key sequence. This has - * to be a number between 1 and 100 (inclusive). - * @param maxSuggestions - * @throws IllegalArgumentException if the number is out of range - */ - public void setMaxSuggestions(int maxSuggestions) { - if (maxSuggestions < 1 || maxSuggestions > 100) { - throw new IllegalArgumentException("maxSuggestions must be between 1 and 100"); - } - mPrefMaxSuggestions = maxSuggestions; - mScores = new int[mPrefMaxSuggestions]; - mBigramScores = new int[PREF_MAX_BIGRAMS]; - collectGarbage(mSuggestions, mPrefMaxSuggestions); - StringBuilderPool.ensureCapacity(mPrefMaxSuggestions, getApproxMaxWordLength()); - } - - /** - * Returns a object which represents suggested words that match the list of character codes - * passed in. This object contents will be overwritten the next time this function is called. - * @param wordComposer contains what is currently being typed - * @param prevWordForBigram previous word (used only for bigram) - * @return suggested words object. - */ - public SuggestedWords getSuggestions(final WordComposer wordComposer, - final CharSequence prevWordForBigram, final ProximityInfo proximityInfo) { - return getSuggestedWordBuilder(wordComposer, prevWordForBigram, - proximityInfo).build(); - } - - private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) { + private static CharSequence capitalizeWord(final boolean all, final boolean first, + final CharSequence word) { if (TextUtils.isEmpty(word) || !(all || first)) return word; final int wordLength = word.length(); - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); // TODO: Must pay attention to locale when changing case. if (all) { sb.append(word.toString().toUpperCase()); @@ -277,41 +234,73 @@ public class Suggest implements Dictionary.WordCallback { } protected void addBigramToSuggestions(CharSequence bigram) { - // TODO: Try to be a little more shrewd with resource allocation. - // At the moment we copy this object because the StringBuilders are pooled (see - // StringBuilderPool.java) and when we are finished using mSuggestions and - // mBigramSuggestions we will take everything from both and insert them back in the - // pool, so we can't allow the same object to be in both lists at the same time. - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); sb.append(bigram); mSuggestions.add(sb); } + private static final WordComposer sEmptyWordComposer = new WordComposer(); + public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) { + LatinImeLogger.onStartSuggestion(prevWordForBigram); + mIsFirstCharCapitalized = false; + mIsAllUpperCase = false; + mTrailingSingleQuotesCount = 0; + mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions); + Arrays.fill(mScores, 0); + + // Treating USER_TYPED as UNIGRAM suggestion for logging now. + LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM); + mConsideredWord = ""; + + Arrays.fill(mBigramScores, 0); + mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS); + + CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); + if (mMainDict != null && mMainDict.isValidWord(lowerPrevWord)) { + prevWordForBigram = lowerPrevWord; + } + for (final Dictionary dictionary : mBigramDictionaries.values()) { + dictionary.getBigrams(sEmptyWordComposer, prevWordForBigram, this); + } + // Nothing entered: return all bigrams for the previous word + int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions); + for (int i = 0; i < insertCount; ++i) { + addBigramToSuggestions(mBigramSuggestions.get(i)); + } + + StringUtils.removeDupes(mSuggestions); + + return new SuggestedWords(SuggestedWords.getFromCharSequenceList(mSuggestions), + false /* typedWordValid */, + false /* hasAutoCorrectionCandidate */, + false /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */, + false /* isObsoleteSuggestions */); + } + // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder - public SuggestedWords.Builder getSuggestedWordBuilder( + public SuggestedWords getSuggestedWords( final WordComposer wordComposer, CharSequence prevWordForBigram, - final ProximityInfo proximityInfo) { + final ProximityInfo proximityInfo, final int correctionMode) { LatinImeLogger.onStartSuggestion(prevWordForBigram); - mAutoCorrection.init(); mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); mIsAllUpperCase = wordComposer.isAllUpperCase(); - collectGarbage(mSuggestions, mPrefMaxSuggestions); + mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); + mSuggestions = new ArrayList<CharSequence>(mPrefMaxSuggestions); Arrays.fill(mScores, 0); - // Save a lowercase version of the original word - String typedWord = wordComposer.getTypedWord(); - if (typedWord != null) { - // Treating USER_TYPED as UNIGRAM suggestion for logging now. - LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, - Dictionary.DataType.UNIGRAM); - } - mTypedWord = typedWord; + final String typedWord = wordComposer.getTypedWord(); + final String consideredWord = mTrailingSingleQuotesCount > 0 + ? typedWord.substring(0, typedWord.length() - mTrailingSingleQuotesCount) + : typedWord; + // Treating USER_TYPED as UNIGRAM suggestion for logging now. + LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM); + mConsideredWord = consideredWord; - if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM - || mCorrectionMode == CORRECTION_BASIC)) { + if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) { // At first character typed, search only the bigrams Arrays.fill(mBigramScores, 0); - collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS); + mBigramSuggestions = new ArrayList<CharSequence>(PREF_MAX_BIGRAMS); if (!TextUtils.isEmpty(prevWordForBigram)) { CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); @@ -321,7 +310,7 @@ public class Suggest implements Dictionary.WordCallback { for (final Dictionary dictionary : mBigramDictionaries.values()) { dictionary.getBigrams(wordComposer, prevWordForBigram, this); } - if (TextUtils.isEmpty(typedWord)) { + if (TextUtils.isEmpty(consideredWord)) { // Nothing entered: return all bigrams for the previous word int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions); for (int i = 0; i < insertCount; ++i) { @@ -329,8 +318,7 @@ public class Suggest implements Dictionary.WordCallback { } } else { // Word entered: return only bigrams that match the first char of the typed word - @SuppressWarnings("null") - final char currentChar = typedWord.charAt(0); + final char currentChar = consideredWord.charAt(0); // TODO: Must pay attention to locale when changing case. final char currentCharUpper = Character.toUpperCase(currentChar); int count = 0; @@ -348,70 +336,126 @@ public class Suggest implements Dictionary.WordCallback { } } else if (wordComposer.size() > 1) { + final WordComposer wordComposerForLookup; + if (mTrailingSingleQuotesCount > 0) { + wordComposerForLookup = new WordComposer(wordComposer); + for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { + wordComposerForLookup.deleteLast(); + } + } else { + wordComposerForLookup = wordComposer; + } // At second character typed, search the unigrams (scores being affected by bigrams) for (final String key : mUnigramDictionaries.keySet()) { // Skip UserUnigramDictionary and WhitelistDictionary to lookup if (key.equals(DICT_KEY_USER_UNIGRAM) || key.equals(DICT_KEY_WHITELIST)) continue; final Dictionary dictionary = mUnigramDictionaries.get(key); - dictionary.getWords(wordComposer, this, proximityInfo); + dictionary.getWords(wordComposerForLookup, this, proximityInfo); } } - final String typedWordString = typedWord == null ? null : typedWord.toString(); - CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase, mIsFirstCharCapitalized, - mWhiteListDictionary.getWhitelistedWord(typedWordString)); + final CharSequence whitelistedWord = capitalizeWord(mIsAllUpperCase, + mIsFirstCharCapitalized, mWhiteListDictionary.getWhitelistedWord(consideredWord)); - mAutoCorrection.updateAutoCorrectionStatus(mUnigramDictionaries, wordComposer, - mSuggestions, mScores, typedWord, mAutoCorrectionThreshold, mCorrectionMode, - whitelistedWord); + final boolean hasAutoCorrection; + if (CORRECTION_FULL == correctionMode || CORRECTION_FULL_BIGRAM == correctionMode) { + final CharSequence autoCorrection = + AutoCorrection.computeAutoCorrectionWord(mUnigramDictionaries, wordComposer, + mSuggestions, mScores, consideredWord, mAutoCorrectionThreshold, + whitelistedWord); + hasAutoCorrection = (null != autoCorrection); + } else { + hasAutoCorrection = false; + } if (whitelistedWord != null) { - mSuggestions.add(0, whitelistedWord); + if (mTrailingSingleQuotesCount > 0) { + final StringBuilder sb = new StringBuilder(whitelistedWord); + for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { + sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE); + } + mSuggestions.add(0, sb.toString()); + } else { + mSuggestions.add(0, whitelistedWord); + } } - if (typedWord != null) { - mSuggestions.add(0, typedWordString); - } - Utils.removeDupes(mSuggestions); + mSuggestions.add(0, typedWord); + StringUtils.removeDupes(mSuggestions); + final ArrayList<SuggestedWordInfo> suggestionsList; if (DBG) { - double normalizedScore = mAutoCorrection.getNormalizedScore(); - ArrayList<SuggestedWords.SuggestedWordInfo> scoreInfoList = - new ArrayList<SuggestedWords.SuggestedWordInfo>(); - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo("+", false)); - for (int i = 0; i < mScores.length; ++i) { - if (normalizedScore > 0) { - final String scoreThreshold = String.format("%d (%4.2f)", mScores[i], - normalizedScore); - scoreInfoList.add( - new SuggestedWords.SuggestedWordInfo(scoreThreshold, false)); - normalizedScore = 0.0; - } else { - final String score = Integer.toString(mScores[i]); - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo(score, false)); - } - } - for (int i = mScores.length; i < mSuggestions.size(); ++i) { - scoreInfoList.add(new SuggestedWords.SuggestedWordInfo("--", false)); - } - return new SuggestedWords.Builder().addWords(mSuggestions, scoreInfoList); + suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, mSuggestions, mScores); + } else { + suggestionsList = SuggestedWords.getFromCharSequenceList(mSuggestions); + } + + // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" + // but still autocorrected from - in the case the whitelist only capitalizes the word. + // The whitelist should be case-insensitive, so it's not possible to be consistent with + // a boolean flag. Right now this is handled with a slight hack in + // WhitelistDictionary#shouldForciblyAutoCorrectFrom. + final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( + getUnigramDictionaries(), consideredWord, wordComposer.isFirstCharCapitalized()); + + boolean autoCorrectionAvailable = hasAutoCorrection; + if (correctionMode == CORRECTION_FULL || correctionMode == CORRECTION_FULL_BIGRAM) { + autoCorrectionAvailable |= !allowsToBeAutoCorrected; + } + // Don't auto-correct words with multiple capital letter + autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); + if (allowsToBeAutoCorrected && suggestionsList.size() > 1 && mAutoCorrectionThreshold > 0 + && Suggest.shouldBlockAutoCorrectionBySafetyNet(typedWord, + suggestionsList.get(1).mWord)) { + autoCorrectionAvailable = false; } - return new SuggestedWords.Builder().addWords(mSuggestions, null); + return new SuggestedWords(suggestionsList, + !allowsToBeAutoCorrected /* typedWordValid */, + autoCorrectionAvailable /* hasAutoCorrectionCandidate */, + allowsToBeAutoCorrected /* allowsToBeAutoCorrected */, + false /* isPunctuationSuggestions */, + false /* isObsoleteSuggestions */); } - public boolean hasAutoCorrection() { - return mAutoCorrection.hasAutoCorrection(); + // This assumes the scores[] array is at least as long as suggestions.size() - 1. + private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo( + final String typedWord, final ArrayList<CharSequence> suggestions, final int[] scores) { + // TODO: this doesn't take into account the fact that removing dupes from mSuggestions + // may have made mScores[] and mSuggestions out of sync. + final CharSequence autoCorrectionSuggestion = suggestions.get(0); + double normalizedScore = BinaryDictionary.calcNormalizedScore( + typedWord, autoCorrectionSuggestion.toString(), scores[0]); + final int suggestionsSize = suggestions.size(); + final ArrayList<SuggestedWordInfo> suggestionsList = + new ArrayList<SuggestedWordInfo>(suggestionsSize); + suggestionsList.add(new SuggestedWordInfo(autoCorrectionSuggestion, "+")); + // Note: i here is the index in mScores[], but the index in mSuggestions is one more + // than i because we added the typed word to mSuggestions without touching mScores. + for (int i = 0; i < scores.length && i < suggestionsSize - 1; ++i) { + final String scoreInfoString; + if (normalizedScore > 0) { + scoreInfoString = String.format("%d (%4.2f)", scores[i], normalizedScore); + normalizedScore = 0.0; + } else { + scoreInfoString = Integer.toString(scores[i]); + } + suggestionsList.add(new SuggestedWordInfo(suggestions.get(i + 1), scoreInfoString)); + } + for (int i = scores.length; i < suggestionsSize; ++i) { + suggestionsList.add(new SuggestedWordInfo(suggestions.get(i), "--")); + } + return suggestionsList; } @Override public boolean addWord(final char[] word, final int offset, final int length, int score, - final int dicTypeId, final Dictionary.DataType dataType) { - Dictionary.DataType dataTypeForLog = dataType; + final int dicTypeId, final int dataType) { + int dataTypeForLog = dataType; final ArrayList<CharSequence> suggestions; final int[] sortedScores; final int prefMaxSuggestions; - if(dataType == Dictionary.DataType.BIGRAM) { + if (dataType == Dictionary.BIGRAM) { suggestions = mBigramSuggestions; sortedScores = mBigramScores; prefMaxSuggestions = PREF_MAX_BIGRAMS; @@ -424,7 +468,7 @@ public class Suggest implements Dictionary.WordCallback { int pos = 0; // Check if it's the same word, only caps are different - if (Utils.equalsIgnoreCase(mTypedWord, word, offset, length)) { + if (StringUtils.equalsIgnoreCase(mConsideredWord, word, offset, length)) { // TODO: remove this surrounding if clause and move this logic to // getSuggestedWordBuilder. if (suggestions.size() > 0) { @@ -433,17 +477,17 @@ public class Suggest implements Dictionary.WordCallback { // frequency to determine the insertion position. This does not ensure strictly // correct ordering, but ensures the top score is on top which is enough for // removing duplicates correctly. - if (Utils.equalsIgnoreCase(currentHighestWord, word, offset, length) + if (StringUtils.equalsIgnoreCase(currentHighestWord, word, offset, length) && score <= sortedScores[0]) { pos = 1; } } } else { - if (dataType == Dictionary.DataType.UNIGRAM) { + if (dataType == Dictionary.UNIGRAM) { // Check if the word was already added before (by bigram data) int bigramSuggestion = searchBigramSuggestion(word,offset,length); if(bigramSuggestion >= 0) { - dataTypeForLog = Dictionary.DataType.BIGRAM; + dataTypeForLog = Dictionary.BIGRAM; // turn freq from bigram into multiplier specified above double multiplier = (((double) mBigramScores[bigramSuggestion]) / MAXIMUM_BIGRAM_FREQUENCY) @@ -474,7 +518,7 @@ public class Suggest implements Dictionary.WordCallback { System.arraycopy(sortedScores, pos, sortedScores, pos + 1, prefMaxSuggestions - pos - 1); sortedScores[pos] = score; - final StringBuilder sb = StringBuilderPool.getStringBuilder(getApproxMaxWordLength()); + final StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); // TODO: Must pay attention to locale when changing case. if (mIsAllUpperCase) { sb.append(new String(word, offset, length).toUpperCase()); @@ -486,12 +530,12 @@ public class Suggest implements Dictionary.WordCallback { } else { sb.append(word, offset, length); } + for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { + sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE); + } suggestions.add(pos, sb); if (suggestions.size() > prefMaxSuggestions) { - final CharSequence garbage = suggestions.remove(prefMaxSuggestions); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - } + suggestions.remove(prefMaxSuggestions); } else { LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog); } @@ -502,39 +546,22 @@ public class Suggest implements Dictionary.WordCallback { // TODO This is almost O(n^2). Might need fix. // search whether the word appeared in bigram data int bigramSuggestSize = mBigramSuggestions.size(); - for(int i = 0; i < bigramSuggestSize; i++) { - if(mBigramSuggestions.get(i).length() == length) { + for (int i = 0; i < bigramSuggestSize; i++) { + if (mBigramSuggestions.get(i).length() == length) { boolean chk = true; - for(int j = 0; j < length; j++) { - if(mBigramSuggestions.get(i).charAt(j) != word[offset+j]) { + for (int j = 0; j < length; j++) { + if (mBigramSuggestions.get(i).charAt(j) != word[offset+j]) { chk = false; break; } } - if(chk) return i; + if (chk) return i; } } return -1; } - private void collectGarbage(ArrayList<CharSequence> suggestions, int prefMaxSuggestions) { - int poolSize = StringBuilderPool.getSize(); - int garbageSize = suggestions.size(); - while (poolSize < prefMaxSuggestions && garbageSize > 0) { - final CharSequence garbage = suggestions.get(garbageSize - 1); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); - poolSize++; - } - garbageSize--; - } - if (poolSize == prefMaxSuggestions + 1) { - Log.w("Suggest", "String pool got too big: " + poolSize); - } - suggestions.clear(); - } - public void close() { final Set<Dictionary> dictionaries = new HashSet<Dictionary>(); dictionaries.addAll(mUnigramDictionaries.values()); @@ -544,4 +571,37 @@ public class Suggest implements Dictionary.WordCallback { } mMainDict = null; } + + // TODO: Resolve the inconsistencies between the native auto correction algorithms and + // this safety net + public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord, + final CharSequence suggestion) { + // Safety net for auto correction. + // Actually if we hit this safety net, it's a bug. + // If user selected aggressive auto correction mode, there is no need to use the safety + // net. + // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, + // we should not use net because relatively edit distance can be big. + final int typedWordLength = typedWord.length(); + if (typedWordLength < Suggest.MINIMUM_SAFETY_NET_CHAR_LENGTH) { + return false; + } + final int maxEditDistanceOfNativeDictionary = + (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; + final int distance = BinaryDictionary.editDistance(typedWord, suggestion.toString()); + if (DBG) { + Log.d(TAG, "Autocorrected edit distance = " + distance + + ", " + maxEditDistanceOfNativeDictionary); + } + if (distance > maxEditDistanceOfNativeDictionary) { + if (DBG) { + Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion); + Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. " + + "Turning off auto-correction."); + } + return true; + } else { + return false; + } + } } diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index ed6359cfa..b63bc6c29 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -20,211 +20,131 @@ import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; public class SuggestedWords { - public static final SuggestedWords EMPTY = new SuggestedWords(null, false, false, false, null); + public static final SuggestedWords EMPTY = new SuggestedWords( + Collections.<SuggestedWordInfo>emptyList(), false, false, false, false, false); - public final List<CharSequence> mWords; public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; + public final boolean mAllowsToBeAutoCorrected; + public final boolean mIsObsoleteSuggestions; private final List<SuggestedWordInfo> mSuggestedWordInfoList; - private boolean mShouldBlockAutoCorrection; - - private SuggestedWords(List<CharSequence> words, boolean typedWordValid, - boolean hasAutoCorrectionCandidate, boolean isPunctuationSuggestions, - List<SuggestedWordInfo> suggestedWordInfoList) { - if (words != null) { - mWords = words; - } else { - mWords = Collections.emptyList(); - } + + public SuggestedWords(final List<SuggestedWordInfo> suggestedWordInfoList, + final boolean typedWordValid, + final boolean hasAutoCorrectionCandidate, + final boolean allowsToBeAutoCorrected, + final boolean isPunctuationSuggestions, + final boolean isObsoleteSuggestions) { + mSuggestedWordInfoList = suggestedWordInfoList; mTypedWordValid = typedWordValid; mHasAutoCorrectionCandidate = hasAutoCorrectionCandidate; + mAllowsToBeAutoCorrected = allowsToBeAutoCorrected; mIsPunctuationSuggestions = isPunctuationSuggestions; - mSuggestedWordInfoList = suggestedWordInfoList; - mShouldBlockAutoCorrection = false; + mIsObsoleteSuggestions = isObsoleteSuggestions; } public int size() { - return mWords.size(); + return mSuggestedWordInfoList.size(); } public CharSequence getWord(int pos) { - return mWords.get(pos); + return mSuggestedWordInfoList.get(pos).mWord; } public SuggestedWordInfo getInfo(int pos) { - return mSuggestedWordInfoList != null ? mSuggestedWordInfoList.get(pos) : null; + return mSuggestedWordInfoList.get(pos); } public boolean hasAutoCorrectionWord() { return mHasAutoCorrectionCandidate && size() > 1 && !mTypedWordValid; } - public boolean hasWordAboveAutoCorrectionScoreThreshold() { - return mHasAutoCorrectionCandidate && ((size() > 1 && !mTypedWordValid) || mTypedWordValid); - } - - public boolean isPunctuationSuggestions() { - return mIsPunctuationSuggestions; + public boolean willAutoCorrect() { + return !mTypedWordValid && mHasAutoCorrectionCandidate; } - public void setShouldBlockAutoCorrection() { - mShouldBlockAutoCorrection = true; + @Override + public String toString() { + // Pretty-print method to help debug + return "SuggestedWords:" + + " mTypedWordValid=" + mTypedWordValid + + " mHasAutoCorrectionCandidate=" + mHasAutoCorrectionCandidate + + " mAllowsToBeAutoCorrected=" + mAllowsToBeAutoCorrected + + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions + + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); } - public boolean shouldBlockAutoCorrection() { - return mShouldBlockAutoCorrection; - } - - public static class Builder { - private List<CharSequence> mWords = new ArrayList<CharSequence>(); - private boolean mTypedWordValid; - private boolean mHasMinimalSuggestion; - private boolean mIsPunctuationSuggestions; - private List<SuggestedWordInfo> mSuggestedWordInfoList = - new ArrayList<SuggestedWordInfo>(); - - public Builder() { - // Nothing to do here. - } - - public Builder addWords(List<CharSequence> words, - List<SuggestedWordInfo> suggestedWordInfoList) { - final int N = words.size(); - for (int i = 0; i < N; ++i) { - SuggestedWordInfo suggestedWordInfo = null; - if (suggestedWordInfoList != null) { - suggestedWordInfo = suggestedWordInfoList.get(i); - } - if (suggestedWordInfo == null) { - suggestedWordInfo = new SuggestedWordInfo(); - } - addWord(words.get(i), suggestedWordInfo); - } - return this; - } - - public Builder addWord(CharSequence word) { - return addWord(word, null, false); - } - - public Builder addWord(CharSequence word, CharSequence debugString, - boolean isPreviousSuggestedWord) { - SuggestedWordInfo info = new SuggestedWordInfo(debugString, isPreviousSuggestedWord); - return addWord(word, info); - } - - private Builder addWord(CharSequence word, SuggestedWordInfo suggestedWordInfo) { - if (!TextUtils.isEmpty(word)) { - mWords.add(word); - // It's okay if suggestedWordInfo is null since it's checked where it's used. - mSuggestedWordInfoList.add(suggestedWordInfo); - } - return this; - } - - public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) { - for (CompletionInfo info : infos) { - if (null != info) addWord(info.getText()); - } - return this; - } - - public Builder setTypedWordValid(boolean typedWordValid) { - mTypedWordValid = typedWordValid; - return this; - } - - public Builder setHasMinimalSuggestion(boolean hasMinimalSuggestion) { - mHasMinimalSuggestion = hasMinimalSuggestion; - return this; - } - - public Builder setIsPunctuationSuggestions() { - mIsPunctuationSuggestions = true; - return this; - } - - // Should get rid of the first one (what the user typed previously) from suggestions - // and replace it with what the user currently typed. - public Builder addTypedWordAndPreviousSuggestions(CharSequence typedWord, - SuggestedWords previousSuggestions) { - mWords.clear(); - mSuggestedWordInfoList.clear(); - final HashSet<String> alreadySeen = new HashSet<String>(); - addWord(typedWord, null, false); - alreadySeen.add(typedWord.toString()); - final int previousSize = previousSuggestions.size(); - for (int pos = 1; pos < previousSize; pos++) { - final String prevWord = previousSuggestions.getWord(pos).toString(); - // Filter out duplicate suggestion. - if (!alreadySeen.contains(prevWord)) { - addWord(prevWord, null, true); - alreadySeen.add(prevWord); - } - } - mTypedWordValid = false; - mHasMinimalSuggestion = false; - return this; - } - - public SuggestedWords build() { - return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion, - mIsPunctuationSuggestions, mSuggestedWordInfoList); - } - - public int size() { - return mWords.size(); + public static ArrayList<SuggestedWordInfo> getFromCharSequenceList( + final List<CharSequence> wordList) { + final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); + for (CharSequence word : wordList) { + if (null != word) result.add(new SuggestedWordInfo(word)); } + return result; + } - public CharSequence getWord(int pos) { - return mWords.get(pos); + public static List<SuggestedWordInfo> getFromApplicationSpecifiedCompletions( + final CompletionInfo[] infos) { + final ArrayList<SuggestedWordInfo> result = new ArrayList<SuggestedWordInfo>(); + for (CompletionInfo info : infos) { + if (null != info) result.add(new SuggestedWordInfo(info.getText())); } + return result; + } - @Override - public String toString() { - // Pretty-print method to help debug - final StringBuilder sb = new StringBuilder("StringBuilder: mTypedWordValid = " - + mTypedWordValid + " ; mHasMinimalSuggestion = " + mHasMinimalSuggestion - + " ; mIsPunctuationSuggestions = " + mIsPunctuationSuggestions - + " --- "); - for (CharSequence s : mWords) { - sb.append(s); - sb.append(" ; "); + // Should get rid of the first one (what the user typed previously) from suggestions + // and replace it with what the user currently typed. + public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions( + final CharSequence typedWord, final SuggestedWords previousSuggestions) { + final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<SuggestedWordInfo>(); + final HashSet<String> alreadySeen = new HashSet<String>(); + suggestionsList.add(new SuggestedWordInfo(typedWord)); + alreadySeen.add(typedWord.toString()); + final int previousSize = previousSuggestions.size(); + for (int pos = 1; pos < previousSize; pos++) { + final String prevWord = previousSuggestions.getWord(pos).toString(); + // Filter out duplicate suggestion. + if (!alreadySeen.contains(prevWord)) { + suggestionsList.add(new SuggestedWordInfo(prevWord)); + alreadySeen.add(prevWord); } - return sb.toString(); } + return suggestionsList; } public static class SuggestedWordInfo { - private final CharSequence mDebugString; - private final boolean mPreviousSuggestedWord; + public final CharSequence mWord; + private final String mDebugString; - public SuggestedWordInfo() { + public SuggestedWordInfo(final CharSequence word) { + mWord = word; mDebugString = ""; - mPreviousSuggestedWord = false; } - public SuggestedWordInfo(CharSequence debugString, boolean previousSuggestedWord) { + public SuggestedWordInfo(final CharSequence word, final String debugString) { + mWord = word; + if (null == debugString) throw new NullPointerException(""); mDebugString = debugString; - mPreviousSuggestedWord = previousSuggestedWord; } public String getDebugString() { - if (mDebugString == null) { - return ""; - } else { - return mDebugString.toString(); - } + return mDebugString; } - public boolean isObsoleteSuggestedWord () { - return mPreviousSuggestedWord; + @Override + public String toString() { + if (TextUtils.isEmpty(mDebugString)) { + return mWord.toString(); + } else { + return mWord.toString() + " (" + mDebugString.toString() + ")"; + } } } } diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java deleted file mode 100644 index 79b3bdebb..000000000 --- a/java/src/com/android/inputmethod/latin/TextEntryState.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2008 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 com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.Utils.RingCharBuffer; - -import android.util.Log; - -public class TextEntryState { - private static final String TAG = TextEntryState.class.getSimpleName(); - private static final boolean DEBUG = false; - - private static final int UNKNOWN = 0; - private static final int START = 1; - private static final int IN_WORD = 2; - private static final int ACCEPTED_DEFAULT = 3; - private static final int PICKED_SUGGESTION = 4; - private static final int PUNCTUATION_AFTER_WORD = 5; - private static final int PUNCTUATION_AFTER_ACCEPTED = 6; - private static final int SPACE_AFTER_ACCEPTED = 7; - private static final int SPACE_AFTER_PICKED = 8; - private static final int UNDO_COMMIT = 9; - private static final int RECORRECTING = 10; - private static final int PICKED_RECORRECTION = 11; - - private static int sState = UNKNOWN; - private static int sPreviousState = UNKNOWN; - - private static void setState(final int newState) { - sPreviousState = sState; - sState = newState; - } - - public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord, - int separatorCode) { - if (typedWord == null) return; - setState(ACCEPTED_DEFAULT); - LatinImeLogger.logOnAutoCorrection( - typedWord.toString(), actualWord.toString(), separatorCode); - if (DEBUG) - displayState("acceptedDefault", "typedWord", typedWord, "actualWord", actualWord); - } - - // State.ACCEPTED_DEFAULT will be changed to other sub-states - // (see "case ACCEPTED_DEFAULT" in typedCharacter() below), - // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state. - public static void backToAcceptedDefault(CharSequence typedWord) { - if (typedWord == null) return; - switch (sState) { - case SPACE_AFTER_ACCEPTED: - case PUNCTUATION_AFTER_ACCEPTED: - case IN_WORD: - setState(ACCEPTED_DEFAULT); - break; - default: - break; - } - if (DEBUG) displayState("backToAcceptedDefault", "typedWord", typedWord); - } - - public static void acceptedTyped(CharSequence typedWord) { - setState(PICKED_SUGGESTION); - if (DEBUG) displayState("acceptedTyped", "typedWord", typedWord); - } - - public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) { - if (sState == RECORRECTING || sState == PICKED_RECORRECTION) { - setState(PICKED_RECORRECTION); - } else { - setState(PICKED_SUGGESTION); - } - if (DEBUG) - displayState("acceptedSuggestion", "typedWord", typedWord, "actualWord", actualWord); - } - - public static void selectedForRecorrection() { - setState(RECORRECTING); - if (DEBUG) displayState("selectedForRecorrection"); - } - - public static void onAbortRecorrection() { - if (sState == RECORRECTING || sState == PICKED_RECORRECTION) { - setState(START); - } - if (DEBUG) displayState("onAbortRecorrection"); - } - - public static void typedCharacter(char c, boolean isSeparator, int x, int y) { - final boolean isSpace = (c == Keyboard.CODE_SPACE); - switch (sState) { - case IN_WORD: - if (isSpace || isSeparator) { - setState(START); - } else { - // State hasn't changed. - } - break; - case ACCEPTED_DEFAULT: - case SPACE_AFTER_PICKED: - case PUNCTUATION_AFTER_ACCEPTED: - if (isSpace) { - setState(SPACE_AFTER_ACCEPTED); - } else if (isSeparator) { - // Swap - setState(PUNCTUATION_AFTER_ACCEPTED); - } else { - setState(IN_WORD); - } - break; - case PICKED_SUGGESTION: - case PICKED_RECORRECTION: - if (isSpace) { - setState(SPACE_AFTER_PICKED); - } else if (isSeparator) { - // Swap - setState(PUNCTUATION_AFTER_ACCEPTED); - } else { - setState(IN_WORD); - } - break; - case START: - case UNKNOWN: - case SPACE_AFTER_ACCEPTED: - case PUNCTUATION_AFTER_WORD: - if (!isSpace && !isSeparator) { - setState(IN_WORD); - } else { - setState(START); - } - break; - case UNDO_COMMIT: - if (isSpace || isSeparator) { - setState(START); - } else { - setState(IN_WORD); - } - break; - case RECORRECTING: - setState(START); - break; - } - RingCharBuffer.getInstance().push(c, x, y); - if (isSeparator) { - LatinImeLogger.logOnInputSeparator(); - } else { - LatinImeLogger.logOnInputChar(); - } - if (DEBUG) displayState("typedCharacter", "char", c, "isSeparator", isSeparator); - } - - public static void backspace() { - if (sState == ACCEPTED_DEFAULT) { - setState(UNDO_COMMIT); - LatinImeLogger.logOnAutoCorrectionCancelled(); - } else if (sState == UNDO_COMMIT) { - setState(IN_WORD); - } - if (DEBUG) displayState("backspace"); - } - - public static void reset() { - setState(START); - if (DEBUG) displayState("reset"); - } - - public static boolean isAcceptedDefault() { - return sState == ACCEPTED_DEFAULT; - } - - public static boolean isSpaceAfterPicked() { - return sState == SPACE_AFTER_PICKED; - } - - public static boolean isUndoCommit() { - return sState == UNDO_COMMIT; - } - - public static boolean isPunctuationAfterAccepted() { - return sState == PUNCTUATION_AFTER_ACCEPTED; - } - - public static boolean isRecorrecting() { - return sState == RECORRECTING || sState == PICKED_RECORRECTION; - } - - public static String getState() { - return stateName(sState); - } - - private static String stateName(int state) { - switch (state) { - case START: return "START"; - case IN_WORD: return "IN_WORD"; - case ACCEPTED_DEFAULT: return "ACCEPTED_DEFAULT"; - case PICKED_SUGGESTION: return "PICKED_SUGGESTION"; - case PUNCTUATION_AFTER_WORD: return "PUNCTUATION_AFTER_WORD"; - case PUNCTUATION_AFTER_ACCEPTED: return "PUNCTUATION_AFTER_ACCEPTED"; - case SPACE_AFTER_ACCEPTED: return "SPACE_AFTER_ACCEPTED"; - case SPACE_AFTER_PICKED: return "SPACE_AFTER_PICKED"; - case UNDO_COMMIT: return "UNDO_COMMIT"; - case RECORRECTING: return "RECORRECTING"; - case PICKED_RECORRECTION: return "PICKED_RECORRECTION"; - default: return "UNKNOWN"; - } - } - - private static void displayState(String title, Object ... args) { - final StringBuilder sb = new StringBuilder(title); - sb.append(':'); - for (int i = 0; i < args.length; i += 2) { - sb.append(' '); - sb.append(args[i]); - sb.append('='); - sb.append(args[i+1].toString()); - } - sb.append(" state="); - sb.append(stateName(sState)); - sb.append(" previous="); - sb.append(stateName(sPreviousState)); - Log.d(TAG, sb.toString()); - } -} diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java index 9e656675e..e6a59d0ab 100644 --- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java @@ -159,7 +159,7 @@ public class UserBigramDictionary extends ExpandableDictionary { */ public int addBigrams(String word1, String word2) { // remove caps if second word is autocapitalized - if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) { + if (mIme != null && mIme.isAutoCapitalized()) { word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1); } // Do not insert a word as a bigram of itself @@ -212,7 +212,8 @@ public class UserBigramDictionary extends ExpandableDictionary { @Override public void loadDictionaryAsync() { // Load the words that correspond to the current input locale - Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale }); + final Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale }); + if (null == cursor) return; try { if (cursor.moveToFirst()) { int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1); @@ -238,7 +239,7 @@ public class UserBigramDictionary extends ExpandableDictionary { /** * Query the database */ - private Cursor query(String selection, String[] selectionArgs) { + private static Cursor query(String selection, String[] selectionArgs) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); // main INNER JOIN frequency ON (main._id=freq.pair_id) @@ -249,11 +250,17 @@ public class UserBigramDictionary extends ExpandableDictionary { qb.setProjectionMap(sDictProjectionMap); // Get the database and run the query - SQLiteDatabase db = sOpenHelper.getReadableDatabase(); - Cursor c = qb.query(db, - new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY }, - selection, selectionArgs, null, null, null); - return c; + try { + SQLiteDatabase db = sOpenHelper.getReadableDatabase(); + Cursor c = qb.query(db, + new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY }, + selection, selectionArgs, null, null, null); + return c; + } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { + // Can't open the database : presumably we can't access storage. That may happen + // when the device is wedged; do a best effort to still start the keyboard. + return null; + } } /** @@ -310,7 +317,7 @@ public class UserBigramDictionary extends ExpandableDictionary { } /** Prune any old data if the database is getting too big. */ - private void checkPruneData(SQLiteDatabase db) { + private static void checkPruneData(SQLiteDatabase db) { db.execSQL("PRAGMA foreign_keys = ON;"); Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID }, null, null, null, null, null); @@ -344,7 +351,18 @@ public class UserBigramDictionary extends ExpandableDictionary { @Override protected Void doInBackground(Void... v) { - SQLiteDatabase db = mDbHelper.getWritableDatabase(); + SQLiteDatabase db = null; + try { + db = mDbHelper.getWritableDatabase(); + } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { + // If we can't open the db, don't do anything. Exit through the next test + // for non-nullity of the db variable. + } + if (null == db) { + // Not much we can do. Just exit. + sUpdatingDB = false; + return null; + } db.execSQL("PRAGMA foreign_keys = ON;"); // Write all the entries to the db Iterator<Bigram> iterator = mMap.iterator(); @@ -380,7 +398,7 @@ public class UserBigramDictionary extends ExpandableDictionary { return null; } - private ContentValues getContentValues(String word1, String word2, String locale) { + private static ContentValues getContentValues(String word1, String word2, String locale) { ContentValues values = new ContentValues(3); values.put(MAIN_COLUMN_WORD1, word1); values.put(MAIN_COLUMN_WORD2, word2); @@ -388,7 +406,7 @@ public class UserBigramDictionary extends ExpandableDictionary { return values; } - private ContentValues getFrequencyContentValues(int pairId, int frequency) { + private static ContentValues getFrequencyContentValues(int pairId, int frequency) { ContentValues values = new ContentValues(2); values.put(FREQ_COLUMN_PAIR_ID, pairId); values.put(FREQ_COLUMN_FREQUENCY, frequency); diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index 0bbbf3995..51b993343 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -18,12 +18,10 @@ package com.android.inputmethod.latin; import android.content.ContentProviderClient; import android.content.ContentResolver; -import android.content.ContentValues; import android.content.Context; +import android.content.Intent; import android.database.ContentObserver; import android.database.Cursor; -import android.net.Uri; -import android.os.RemoteException; import android.provider.UserDictionary.Words; import android.text.TextUtils; @@ -38,11 +36,9 @@ public class UserDictionary extends ExpandableDictionary { Words.FREQUENCY, }; - private static final String[] PROJECTION_ADD = { - Words._ID, - Words.FREQUENCY, - Words.LOCALE, - }; + // 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; @@ -134,7 +130,11 @@ public class UserDictionary extends ExpandableDictionary { final Cursor cursor = getContext().getContentResolver() .query(Words.CONTENT_URI, PROJECTION_QUERY, request.toString(), requestArguments, null); - addWords(cursor); + try { + addWords(cursor); + } finally { + if (null != cursor) cursor.close(); + } } public boolean isEnabled() { @@ -160,57 +160,17 @@ public class UserDictionary extends ExpandableDictionary { public synchronized void addWord(final String word, final int frequency) { // Force load the dictionary here synchronously if (getRequiresReload()) loadDictionaryAsync(); + // 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() >= getMaxWordLength()) return; - super.addWord(word, frequency); - - // Update the user dictionary provider - final ContentValues values = new ContentValues(5); - values.put(Words.WORD, word); - values.put(Words.FREQUENCY, frequency); - values.put(Words.LOCALE, mLocale); - values.put(Words.APP_ID, 0); - - final ContentResolver contentResolver = getContext().getContentResolver(); - final ContentProviderClient client = - contentResolver.acquireContentProviderClient(Words.CONTENT_URI); - if (null == client) return; - new Thread("addWord") { - @Override - public void run() { - Cursor cursor = null; - try { - cursor = client.query(Words.CONTENT_URI, PROJECTION_ADD, - "word=? and ((locale IS NULL) or (locale=?))", - new String[] { word, mLocale }, null); - if (cursor != null && cursor.moveToFirst()) { - final String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE)); - // If locale is null, we will not override the entry. - if (locale != null && locale.equals(mLocale.toString())) { - final long id = cursor.getLong(cursor.getColumnIndex(Words._ID)); - final Uri uri = - Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id)); - // Update the entry with new frequency value. - client.update(uri, values, null, null); - } - } else { - // Insert new entry. - client.insert(Words.CONTENT_URI, values); - } - } catch (RemoteException e) { - // If we come here, the activity is already about to be killed, and we - // have no means of contacting the content provider any more. - // See ContentResolver#insert, inside the catch(){} - } finally { - if (null != cursor) cursor.close(); - client.release(); - } - } - }.start(); - - // In case the above does a synchronous callback of the change observer - setRequiresReload(false); + // 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); + getContext().startActivity(intent); } @Override @@ -242,6 +202,5 @@ public class UserDictionary extends ExpandableDictionary { cursor.moveToNext(); } } - cursor.close(); } } diff --git a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java index e41230b3c..869865d7b 100644 --- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java @@ -121,7 +121,8 @@ public class UserUnigramDictionary extends ExpandableDictionary { public void loadDictionaryAsync() { if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; // Load the words that correspond to the current input locale - Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); + final Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); + if (null == cursor) return; try { if (cursor.moveToFirst()) { int wordIndex = cursor.getColumnIndex(COLUMN_WORD); @@ -149,7 +150,7 @@ public class UserUnigramDictionary extends ExpandableDictionary { final int length = word.length(); // Don't add very short or very long words. if (length < 2 || length > getMaxWordLength()) return; - if (mIme.getCurrentWord().isAutoCapitalized()) { + if (mIme.isAutoCapitalized()) { // Remove caps before adding word = Character.toLowerCase(word.charAt(0)) + word.substring(1); } @@ -172,7 +173,7 @@ public class UserUnigramDictionary extends ExpandableDictionary { // Nothing pending? Return if (mPendingWrites.isEmpty()) return; // Create a background thread to write the pending entries - new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute(); + new UpdateDbTask(sOpenHelper, mPendingWrites, mLocale).execute(); // Create a new map for writing new entries into while the old one is written to db mPendingWrites = new HashMap<String, Integer>(); } @@ -206,16 +207,22 @@ public class UserUnigramDictionary extends ExpandableDictionary { } } - private Cursor query(String selection, String[] selectionArgs) { + private static Cursor query(String selection, String[] selectionArgs) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(USER_UNIGRAM_DICT_TABLE_NAME); qb.setProjectionMap(sDictProjectionMap); // Get the database and run the query - SQLiteDatabase db = sOpenHelper.getReadableDatabase(); - Cursor c = qb.query(db, null, selection, selectionArgs, null, null, - DEFAULT_SORT_ORDER); - return c; + try { + SQLiteDatabase db = sOpenHelper.getReadableDatabase(); + Cursor c = qb.query(db, null, selection, selectionArgs, null, null, + DEFAULT_SORT_ORDER); + return c; + } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { + // Can't open the database : presumably we can't access storage. That may happen + // when the device is wedged; do a best effort to still start the keyboard. + return null; + } } /** @@ -227,8 +234,8 @@ public class UserUnigramDictionary extends ExpandableDictionary { private final DatabaseHelper mDbHelper; private final String mLocale; - public UpdateDbTask(@SuppressWarnings("unused") Context context, DatabaseHelper openHelper, - HashMap<String, Integer> pendingWrites, String locale) { + public UpdateDbTask(DatabaseHelper openHelper, HashMap<String, Integer> pendingWrites, + String locale) { mMap = pendingWrites; mLocale = locale; mDbHelper = openHelper; @@ -236,7 +243,14 @@ public class UserUnigramDictionary extends ExpandableDictionary { @Override protected Void doInBackground(Void... v) { - SQLiteDatabase db = mDbHelper.getWritableDatabase(); + SQLiteDatabase db = null; + try { + db = mDbHelper.getWritableDatabase(); + } catch (android.database.sqlite.SQLiteCantOpenDatabaseException e) { + // With no access to the DB, this is moot. Do nothing: we'll exit through the + // test for null == db. + } + if (null == db) return null; // Write all the entries to the db Set<Entry<String,Integer>> mEntries = mMap.entrySet(); for (Entry<String,Integer> entry : mEntries) { @@ -251,7 +265,7 @@ public class UserUnigramDictionary extends ExpandableDictionary { return null; } - private ContentValues getContentValues(String word, int frequency, String locale) { + private static ContentValues getContentValues(String word, int frequency, String locale) { ContentValues values = new ContentValues(4); values.put(COLUMN_WORD, word); values.put(COLUMN_FREQUENCY, frequency); diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index b29ff1975..a7de47c58 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -17,48 +17,36 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Resources; +import android.content.Intent; +import android.content.pm.PackageManager; import android.inputmethodservice.InputMethodService; +import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; +import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; -import android.text.InputType; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; -import android.view.inputmethod.EditorInfo; -import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; +import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; -import java.util.List; -import java.util.Locale; public class Utils { - private static final String TAG = Utils.class.getSimpleName(); - private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4; - private static boolean DBG = LatinImeLogger.sDBG; - private static boolean DBG_EDIT_DISTANCE = false; - private Utils() { - // Intentional empty constructor for utility class. + // This utility class is not publicly instantiable. } /** @@ -112,108 +100,6 @@ public class Utils { } } - public static boolean hasMultipleEnabledIMEsOrSubtypes( - final InputMethodManagerCompatWrapper imm, - final boolean shouldIncludeAuxiliarySubtypes) { - final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList(); - - // Number of the filtered IMEs - int filteredImisCount = 0; - - for (InputMethodInfoCompatWrapper imi : enabledImis) { - // We can return true immediately after we find two or more filtered IMEs. - if (filteredImisCount > 1) return true; - final List<InputMethodSubtypeCompatWrapper> subtypes = - imm.getEnabledInputMethodSubtypeList(imi, true); - // IMEs that have no subtypes should be counted. - if (subtypes.isEmpty()) { - ++filteredImisCount; - continue; - } - - int auxCount = 0; - for (InputMethodSubtypeCompatWrapper subtype : subtypes) { - if (subtype.isAuxiliary()) { - ++auxCount; - } - } - final int nonAuxCount = subtypes.size() - auxCount; - - // IMEs that have one or more non-auxiliary subtypes should be counted. - // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary - // subtypes should be counted as well. - if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { - ++filteredImisCount; - continue; - } - } - - return filteredImisCount > 1 - // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled - // input method subtype (The current IME should be LatinIME.) - || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1; - } - - public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) { - return getInputMethodInfo(imm, packageName).getId(); - } - - public static InputMethodInfoCompatWrapper getInputMethodInfo( - InputMethodManagerCompatWrapper imm, String packageName) { - for (final InputMethodInfoCompatWrapper imi : imm.getEnabledInputMethodList()) { - if (imi.getPackageName().equals(packageName)) - return imi; - } - throw new RuntimeException("Can not find input method id for " + packageName); - } - - // TODO: Resolve the inconsistencies between the native auto correction algorithms and - // this safety net - public static boolean shouldBlockAutoCorrectionBySafetyNet(SuggestedWords suggestions, - Suggest suggest) { - // Safety net for auto correction. - // Actually if we hit this safety net, it's actually a bug. - if (suggestions.size() <= 1 || suggestions.mTypedWordValid) return false; - // If user selected aggressive auto correction mode, there is no need to use the safety - // net. - if (suggest.isAggressiveAutoCorrectionMode()) return false; - final CharSequence typedWord = suggestions.getWord(0); - // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH, - // we should not use net because relatively edit distance can be big. - if (typedWord.length() < MINIMUM_SAFETY_NET_CHAR_LENGTH) return false; - final CharSequence suggestionWord = suggestions.getWord(1); - final int typedWordLength = typedWord.length(); - final int maxEditDistanceOfNativeDictionary = - (typedWordLength < 5 ? 2 : typedWordLength / 2) + 1; - final int distance = Utils.editDistance(typedWord, suggestionWord); - if (DBG) { - Log.d(TAG, "Autocorrected edit distance = " + distance - + ", " + maxEditDistanceOfNativeDictionary); - } - if (distance > maxEditDistanceOfNativeDictionary) { - if (DBG) { - Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestionWord); - Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. " - + "Turning off auto-correction."); - } - return true; - } else { - return false; - } - } - - public static boolean canBeFollowedByPeriod(final int codePoint) { - // TODO: Check again whether there really ain't a better way to check this. - // TODO: This should probably be language-dependant... - return Character.isLetterOrDigit(codePoint) - || codePoint == Keyboard.CODE_SINGLE_QUOTE - || codePoint == Keyboard.CODE_DOUBLE_QUOTE - || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS - || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET - || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET - || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET; - } - /* package */ static class RingCharBuffer { private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; @@ -242,10 +128,11 @@ public class Utils { UsabilityStudyLogUtils.getInstance().init(context); return sRingCharBuffer; } - private int normalize(int in) { + private static int normalize(int in) { int ret = in % BUFSIZE; return ret < 0 ? ret + BUFSIZE : ret; } + // TODO: accept code points public void push(char c, int x, int y) { if (!mEnabled) return; if (mUsabilityStudy) { @@ -317,49 +204,6 @@ public class Utils { } } - - /* Damerau-Levenshtein distance */ - public static int editDistance(CharSequence s, CharSequence t) { - if (s == null || t == null) { - throw new IllegalArgumentException("editDistance: Arguments should not be null."); - } - final int sl = s.length(); - final int tl = t.length(); - int[][] dp = new int [sl + 1][tl + 1]; - for (int i = 0; i <= sl; i++) { - dp[i][0] = i; - } - for (int j = 0; j <= tl; j++) { - dp[0][j] = j; - } - for (int i = 0; i < sl; ++i) { - for (int j = 0; j < tl; ++j) { - final char sc = Character.toLowerCase(s.charAt(i)); - final char tc = Character.toLowerCase(t.charAt(j)); - final int cost = sc == tc ? 0 : 1; - dp[i + 1][j + 1] = Math.min( - dp[i][j + 1] + 1, Math.min(dp[i + 1][j] + 1, dp[i][j] + cost)); - // Overwrite for transposition cases - if (i > 0 && j > 0 - && sc == Character.toLowerCase(t.charAt(j - 1)) - && tc == Character.toLowerCase(s.charAt(i - 1))) { - dp[i + 1][j + 1] = Math.min(dp[i + 1][j + 1], dp[i - 1][j - 1] + cost); - } - } - } - if (DBG_EDIT_DISTANCE) { - Log.d(TAG, "editDistance:" + s + "," + t); - for (int i = 0; i < dp.length; ++i) { - StringBuffer sb = new StringBuffer(); - for (int j = 0; j < dp[i].length; ++j) { - sb.append(dp[i][j]).append(','); - } - Log.d(TAG, i + ":" + sb.toString()); - } - } - return dp[sl][tl]; - } - // Get the current stack trace public static String getStackTrace() { StringBuilder sb = new StringBuilder(); @@ -373,55 +217,6 @@ public class Utils { return sb.toString(); } - // In dictionary.cpp, getSuggestion() method, - // suggestion scores are computed using the below formula. - // original score - // := pow(mTypedLetterMultiplier (this is defined 2), - // (the number of matched characters between typed word and suggested word)) - // * (individual word's score which defined in the unigram dictionary, - // and this score is defined in range [0, 255].) - // Then, the following processing is applied. - // - If the dictionary word is matched up to the point of the user entry - // (full match up to min(before.length(), after.length()) - // => Then multiply by FULL_MATCHED_WORDS_PROMOTION_RATE (this is defined 1.2) - // - If the word is a true full match except for differences in accents or - // capitalization, then treat it as if the score was 255. - // - If before.length() == after.length() - // => multiply by mFullWordMultiplier (this is defined 2)) - // So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2 - // For historical reasons we ignore the 1.2 modifier (because the measure for a good - // autocorrection threshold was done at a time when it didn't exist). This doesn't change - // the result. - // So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2. - private static final int MAX_INITIAL_SCORE = 255; - private static final int TYPED_LETTER_MULTIPLIER = 2; - private static final int FULL_WORD_MULTIPLIER = 2; - private static final int S_INT_MAX = 2147483647; - public static double calcNormalizedScore(CharSequence before, CharSequence after, int score) { - final int beforeLength = before.length(); - final int afterLength = after.length(); - if (beforeLength == 0 || afterLength == 0) return 0; - final int distance = editDistance(before, after); - // If afterLength < beforeLength, the algorithm is suggesting a word by excessive character - // correction. - int spaceCount = 0; - for (int i = 0; i < afterLength; ++i) { - if (after.charAt(i) == Keyboard.CODE_SPACE) { - ++spaceCount; - } - } - if (spaceCount == afterLength) return 0; - final double maximumScore = score == S_INT_MAX ? S_INT_MAX : MAX_INITIAL_SCORE - * Math.pow( - TYPED_LETTER_MULTIPLIER, Math.min(beforeLength, afterLength - spaceCount)) - * FULL_WORD_MULTIPLIER; - // add a weight based on edit distance. - // distance <= max(afterLength, beforeLength) == afterLength, - // so, 0 <= distance / afterLength <= 1 - final double weight = 1.0 - (double) distance / afterLength; - return (score / maximumScore) * weight; - } - public static class UsabilityStudyLogUtils { private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName(); private static final String FILENAME = "log.txt"; @@ -437,7 +232,7 @@ public class Utils { private UsabilityStudyLogUtils() { mDate = new Date(); - mDateFormat = new SimpleDateFormat("dd MMM HH:mm:ss.SSS"); + mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); HandlerThread handlerThread = new HandlerThread("UsabilityStudyLogUtils logging task", Process.THREAD_PRIORITY_BACKGROUND); @@ -465,7 +260,7 @@ public class Utils { } } - public void writeBackSpace() { + public static void writeBackSpace() { UsabilityStudyLogUtils.getInstance().write("<backspace>\t0\t0"); } @@ -504,32 +299,89 @@ public class Utils { }); } - public void printAll() { + private synchronized String getBufferedLogs() { + mWriter.flush(); + StringBuilder sb = new StringBuilder(); + BufferedReader br = getBufferedReader(); + String line; + try { + while ((line = br.readLine()) != null) { + sb.append('\n'); + sb.append(line); + } + } catch (IOException e) { + Log.e(USABILITY_TAG, "Can't read log file."); + } finally { + if (LatinImeLogger.sDBG) { + Log.d(USABILITY_TAG, "Got all buffered logs\n" + sb.toString()); + } + try { + br.close(); + } catch (IOException e) { + // ignore. + } + } + return sb.toString(); + } + + public void emailResearcherLogsAll() { mLoggingHandler.post(new Runnable() { @Override public void run() { + final Date date = new Date(); + date.setTime(System.currentTimeMillis()); + final String currentDateTimeString = + new SimpleDateFormat("yyyyMMdd-HHmmssZ").format(date); + if (mFile == null) { + Log.w(USABILITY_TAG, "No internal log file found."); + return; + } + if (mIms.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + Log.w(USABILITY_TAG, "Doesn't have the permission WRITE_EXTERNAL_STORAGE"); + return; + } mWriter.flush(); - StringBuilder sb = new StringBuilder(); - BufferedReader br = getBufferedReader(); - String line; + final String destPath = Environment.getExternalStorageDirectory() + + "/research-" + currentDateTimeString + ".log"; + final File destFile = new File(destPath); try { - while ((line = br.readLine()) != null) { - sb.append('\n'); - sb.append(line); - } - } catch (IOException e) { - Log.e(USABILITY_TAG, "Can't read log file."); - } finally { - if (LatinImeLogger.sDBG) { - Log.d(USABILITY_TAG, "output all logs\n" + sb.toString()); - } - mIms.getCurrentInputConnection().commitText(sb.toString(), 0); - try { - br.close(); - } catch (IOException e) { - // ignore. - } + final FileChannel src = (new FileInputStream(mFile)).getChannel(); + final FileChannel dest = (new FileOutputStream(destFile)).getChannel(); + src.transferTo(0, src.size(), dest); + src.close(); + dest.close(); + } catch (FileNotFoundException e1) { + Log.w(USABILITY_TAG, e1); + return; + } catch (IOException e2) { + Log.w(USABILITY_TAG, e2); + return; } + if (destFile == null || !destFile.exists()) { + Log.w(USABILITY_TAG, "Dest file doesn't exist."); + return; + } + final Intent intent = new Intent(Intent.ACTION_SEND); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (LatinImeLogger.sDBG) { + Log.d(USABILITY_TAG, "Destination file URI is " + destFile.toURI()); + } + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath)); + intent.putExtra(Intent.EXTRA_SUBJECT, + "[Research Logs] " + currentDateTimeString); + mIms.startActivity(intent); + } + }); + } + + public void printAll() { + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + mIms.getCurrentInputConnection().commitText(getBufferedLogs(), 0); } }); } @@ -570,134 +422,6 @@ public class Utils { } } - public static int getKeyboardMode(EditorInfo editorInfo) { - if (editorInfo == null) - return KeyboardId.MODE_TEXT; - - final int inputType = editorInfo.inputType; - final int variation = inputType & InputType.TYPE_MASK_VARIATION; - - switch (inputType & InputType.TYPE_MASK_CLASS) { - case InputType.TYPE_CLASS_NUMBER: - case InputType.TYPE_CLASS_DATETIME: - return KeyboardId.MODE_NUMBER; - case InputType.TYPE_CLASS_PHONE: - return KeyboardId.MODE_PHONE; - case InputType.TYPE_CLASS_TEXT: - if (InputTypeCompatUtils.isEmailVariation(variation)) { - return KeyboardId.MODE_EMAIL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_URI) { - return KeyboardId.MODE_URL; - } else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { - return KeyboardId.MODE_IM; - } else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) { - return KeyboardId.MODE_TEXT; - } else { - return KeyboardId.MODE_TEXT; - } - default: - return KeyboardId.MODE_TEXT; - } - } - - public static boolean containsInCsv(String key, String csv) { - if (csv == null) - return false; - for (String option : csv.split(",")) { - if (option.equals(key)) - return true; - } - return false; - } - - public static boolean inPrivateImeOptions(String packageName, String key, - EditorInfo editorInfo) { - if (editorInfo == null) - return false; - return containsInCsv(packageName != null ? packageName + "." + key : key, - editorInfo.privateImeOptions); - } - - /** - * Returns a main dictionary resource id - * @return main dictionary resource id - */ - public static int getMainDictionaryResourceId(Resources res) { - final String MAIN_DIC_NAME = "main"; - String packageName = LatinIME.class.getPackage().getName(); - return res.getIdentifier(MAIN_DIC_NAME, "raw", packageName); - } - - public static void loadNativeLibrary() { - try { - System.loadLibrary("jni_latinime"); - } catch (UnsatisfiedLinkError ule) { - Log.e(TAG, "Could not load native library jni_latinime"); - } - } - - /** - * Returns true if a and b are equal ignoring the case of the character. - * @param a first character to check - * @param b second character to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(char a, char b) { - // Some language, such as Turkish, need testing both cases. - return a == b - || Character.toLowerCase(a) == Character.toLowerCase(b) - || Character.toUpperCase(a) == Character.toUpperCase(b); - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if they are - * both null. - * @param a first CharSequence to check - * @param b second CharSequence to check - * @return {@code true} if a and b are equal, {@code false} otherwise. - */ - public static boolean equalsIgnoreCase(CharSequence a, CharSequence b) { - if (a == b) - return true; // including both a and b are null. - if (a == null || b == null) - return false; - final int length = a.length(); - if (length != b.length()) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b.charAt(i))) - return false; - } - return true; - } - - /** - * Returns true if a and b are equal ignoring the case of the characters, including if a is null - * and b is zero length. - * @param a CharSequence to check - * @param b character array to check - * @param offset start offset of array b - * @param length length of characters in array b - * @return {@code true} if a and b are equal, {@code false} otherwise. - * @throws IndexOutOfBoundsException - * if {@code offset < 0 || length < 0 || offset + length > data.length}. - * @throws NullPointerException if {@code b == null}. - */ - public static boolean equalsIgnoreCase(CharSequence a, char[] b, int offset, int length) { - if (offset < 0 || length < 0 || length > b.length - offset) - throw new IndexOutOfBoundsException("array.length=" + b.length + " offset=" + offset - + " length=" + length); - if (a == null) - return length == 0; // including a is null and b is zero length. - if (a.length() != length) - return false; - for (int i = 0; i < length; i++) { - if (!equalsIgnoreCase(a.charAt(i), b[offset + i])) - return false; - } - return true; - } - public static float getDipScale(Context context) { final float scale = context.getResources().getDisplayMetrics().density; return scale; @@ -708,110 +432,37 @@ public class Utils { return (int) (dip * scale + 0.5); } - /** - * Remove duplicates from an array of strings. - * - * This method will always keep the first occurence of all strings at their position - * in the array, removing the subsequent ones. - */ - public static void removeDupes(final ArrayList<CharSequence> suggestions) { - if (suggestions.size() < 2) return; - int i = 1; - // Don't cache suggestions.size(), since we may be removing items - while (i < suggestions.size()) { - final CharSequence cur = suggestions.get(i); - // Compare each suggestion with each previous suggestion - for (int j = 0; j < i; j++) { - CharSequence previous = suggestions.get(j); - if (TextUtils.equals(cur, previous)) { - removeFromSuggestions(suggestions, i); - i--; - break; - } - } - i++; - } - } - - private static void removeFromSuggestions(final ArrayList<CharSequence> suggestions, - final int index) { - final CharSequence garbage = suggestions.remove(index); - if (garbage instanceof StringBuilder) { - StringBuilderPool.recycle((StringBuilder)garbage); + public static class Stats { + public static void onNonSeparator(final char code, final int x, + final int y) { + RingCharBuffer.getInstance().push(code, x, y); + LatinImeLogger.logOnInputChar(); } - } - public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { - if (returnsNameInThisLocale) { - return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); - } else { - return toTitleCase(locale.getDisplayName(), locale); + public static void onSeparator(final int code, final int x, + final int y) { + // TODO: accept code points + RingCharBuffer.getInstance().push((char)code, x, y); + LatinImeLogger.logOnInputSeparator(); } - } - - public static String getDisplayLanguage(Locale locale) { - return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); - } - - public static String getMiddleDisplayLanguage(Locale locale) { - return toTitleCase((LocaleUtils.constructLocaleFromString( - locale.getLanguage()).getDisplayLanguage(locale)), locale); - } - - public static String getShortDisplayLanguage(Locale locale) { - return toTitleCase(locale.getLanguage(), locale); - } - public static String toTitleCase(String s, Locale locale) { - if (s.length() <= 1) { - // TODO: is this really correct? Shouldn't this be s.toUpperCase()? - return s; - } - // TODO: fix the bugs below - // - This does not work for Greek, because it returns upper case instead of title case. - // - It does not work for Serbian, because it fails to account for the "lj" character, - // which should be "Lj" in title case and "LJ" in upper case. - // - It does not work for Dutch, because it fails to account for the "ij" digraph, which - // are two different characters but both should be capitalized as "IJ" as if they were - // a single letter. - // - It also does not work with unicode surrogate code points. - return s.toUpperCase(locale).charAt(0) + s.substring(1); - } - - public static int getCurrentVibrationDuration(SharedPreferences sp, Resources res) { - final int ms = sp.getInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, -1); - if (ms >= 0) { - return ms; - } - final String[] durationPerHardwareList = res.getStringArray( - R.array.keypress_vibration_durations); - final String hardwarePrefix = Build.HARDWARE + ","; - for (final String element : durationPerHardwareList) { - if (element.startsWith(hardwarePrefix)) { - return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1)); - } + public static void onAutoCorrection(final String typedWord, final String correctedWord, + final int separatorCode) { + if (TextUtils.isEmpty(typedWord)) return; + LatinImeLogger.logOnAutoCorrection(typedWord, correctedWord, separatorCode); } - return -1; - } - public static float getCurrentKeypressSoundVolume(SharedPreferences sp, Resources res) { - final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f); - if (volume >= 0) { - return volume; - } - - final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes); - final String hardwarePrefix = Build.HARDWARE + ","; - for (final String element : volumePerHardwareList) { - if (element.startsWith(hardwarePrefix)) { - return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1)); - } + public static void onAutoCorrectionCancellation() { + LatinImeLogger.logOnAutoCorrectionCancelled(); } - return -1.0f; } - public static boolean willAutoCorrect(SuggestedWords suggestions) { - return !suggestions.mTypedWordValid && suggestions.mHasAutoCorrectionCandidate - && !suggestions.shouldBlockAutoCorrection(); + public static String getDebugInfo(final SuggestedWords suggestions, final int pos) { + if (!LatinImeLogger.sDBG) return null; + final SuggestedWordInfo wordInfo = suggestions.getInfo(pos); + if (wordInfo == null) return null; + final String info = wordInfo.getDebugString(); + if (TextUtils.isEmpty(info)) return null; + return info; } } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index adc5637f6..126ac47e7 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -1,12 +1,12 @@ /* * Copyright (C) 2008 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 @@ -16,9 +16,15 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; +import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.ArrayList; +import java.util.Arrays; /** * A place to store the currently composing word with information such as adjacent key codes as well @@ -28,31 +34,31 @@ public class WordComposer { public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE; public static final int NOT_A_COORDINATE = -1; - /** - * The list of unicode values for each keystroke (including surrounding keys) - */ - private ArrayList<int[]> mCodes; + final static int N = BinaryDictionary.MAX_WORD_LENGTH; + private ArrayList<int[]> mCodes; private int[] mXCoordinates; private int[] mYCoordinates; - private StringBuilder mTypedWord; + private CharSequence mAutoCorrection; + // Cache these values for performance private int mCapsCount; - private boolean mAutoCapitalized; - + private int mTrailingSingleQuotesCount; + /** * Whether the user chose to capitalize the first char of the word. */ private boolean mIsFirstCharCapitalized; public WordComposer() { - final int N = BinaryDictionary.MAX_WORD_LENGTH; mCodes = new ArrayList<int[]>(N); mTypedWord = new StringBuilder(N); mXCoordinates = new int[N]; mYCoordinates = new int[N]; + mAutoCorrection = null; + mTrailingSingleQuotesCount = 0; } public WordComposer(WordComposer source) { @@ -62,11 +68,12 @@ public class WordComposer { public void init(WordComposer source) { mCodes = new ArrayList<int[]>(source.mCodes); mTypedWord = new StringBuilder(source.mTypedWord); - mXCoordinates = source.mXCoordinates; - mYCoordinates = source.mYCoordinates; + mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length); + mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length); mCapsCount = source.mCapsCount; mIsFirstCharCapitalized = source.mIsFirstCharCapitalized; mAutoCapitalized = source.mAutoCapitalized; + mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount; } /** @@ -75,8 +82,10 @@ public class WordComposer { public void reset() { mCodes.clear(); mTypedWord.setLength(0); + mAutoCorrection = null; mCapsCount = 0; mIsFirstCharCapitalized = false; + mTrailingSingleQuotesCount = 0; } /** @@ -84,7 +93,11 @@ public class WordComposer { * @return the number of keystrokes */ public final int size() { - return mTypedWord.length(); + return mCodes.size(); + } + + public final boolean isComposingWord() { + return mCodes.size() > 0; } /** @@ -109,23 +122,120 @@ public class WordComposer { return previous && !Character.isUpperCase(codePoint); } + // TODO: remove input keyDetector + public void add(int primaryCode, int x, int y, KeyDetector keyDetector) { + final int[] codes; + final int keyX; + final int keyY; + if (x == KeyboardActionListener.SPELL_CHECKER_COORDINATE + || y == KeyboardActionListener.SPELL_CHECKER_COORDINATE) { + // only used for tests in InputLogicTests + addKeyForSpellChecker(primaryCode, AndroidSpellCheckerService.SCRIPT_LATIN); + return; + } else if (x == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE + || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) { + codes = new int[] { primaryCode }; + keyX = x; + keyY = y; + } else { + codes = keyDetector.newCodeArray(); + keyDetector.getNearbyCodes(x, y, codes); + keyX = keyDetector.getTouchX(x); + keyY = keyDetector.getTouchY(y); + } + add(primaryCode, codes, keyX, keyY); + } + + // TODO: remove this function + public void addKeyForSpellChecker(int primaryCode, int script) { + final int[] proximities; + final int proximityIndex = + SpellCheckerProximityInfo.getIndexOfCodeForScript(primaryCode, script); + if (-1 == proximityIndex) { + proximities = new int[] { primaryCode }; + } else { + // TODO: an initial examination seems to reveal this is actually used + // read-only. It should be possible to compute the arrays statically once + // and skip doing a copy each time here. + proximities = Arrays.copyOfRange( + SpellCheckerProximityInfo.getProximityForScript(script), + proximityIndex, + proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); + } + add(primaryCode, proximities, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + } + /** * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. * @param codes the array of unicode values */ - public void add(int primaryCode, int[] codes, int x, int y) { - final int newIndex = size(); - mTypedWord.append((char) primaryCode); + private void add(int primaryCode, int[] codes, int keyX, int keyY) { + final int newIndex = mCodes.size(); + mTypedWord.appendCodePoint(primaryCode); correctPrimaryJuxtapos(primaryCode, codes); mCodes.add(codes); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mXCoordinates[newIndex] = x; - mYCoordinates[newIndex] = y; + mXCoordinates[newIndex] = keyX; + mYCoordinates[newIndex] = keyY; } mIsFirstCharCapitalized = isFirstCharCapitalized( newIndex, primaryCode, mIsFirstCharCapitalized); if (Character.isUpperCase(primaryCode)) mCapsCount++; + if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) { + ++mTrailingSingleQuotesCount; + } else { + mTrailingSingleQuotesCount = 0; + } + mAutoCorrection = null; + } + + /** + * Internal method to retrieve reasonable proximity info for a character. + */ + private void addKeyInfo(final int codePoint, final Keyboard keyboard, + final KeyDetector keyDetector) { + for (final Key key : keyboard.mKeys) { + if (key.mCode == codePoint) { + final int x = key.mX + key.mWidth / 2; + final int y = key.mY + key.mHeight / 2; + final int[] codes = keyDetector.newCodeArray(); + keyDetector.getNearbyCodes(x, y, codes); + add(codePoint, codes, x, y); + return; + } + } + add(codePoint, new int[] { codePoint }, + WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + } + + /** + * Set the currently composing word to the one passed as an argument. + * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity. + */ + public void setComposingWord(final CharSequence word, final Keyboard keyboard, + final KeyDetector keyDetector) { + reset(); + final int length = word.length(); + for (int i = 0; i < length; i = Character.offsetByCodePoints(word, i, 1)) { + int codePoint = Character.codePointAt(word, i); + addKeyInfo(codePoint, keyboard, keyDetector); + } + } + + /** + * Shortcut for the above method, this will create a new KeyDetector for the passed keyboard. + */ + public void setComposingWord(final CharSequence word, final Keyboard keyboard) { + final KeyDetector keyDetector = new KeyDetector(0); + keyDetector.setKeyboard(keyboard, 0, 0); + keyDetector.setProximityCorrectionEnabled(true); + keyDetector.setProximityThreshold(keyboard.mMostCommonKeyWidth); + setComposingWord(word, keyboard, keyDetector); } /** @@ -135,7 +245,7 @@ public class WordComposer { * @param primaryCode the preferred character * @param codes array of codes based on distance from touch point */ - private void correctPrimaryJuxtapos(int primaryCode, int[] codes) { + private static void correctPrimaryJuxtapos(int primaryCode, int[] codes) { if (codes.length < 2) return; if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { codes[1] = codes[0]; @@ -147,27 +257,45 @@ public class WordComposer { * Delete the last keystroke as a result of hitting backspace. */ public void deleteLast() { - final int size = size(); + final int size = mCodes.size(); if (size > 0) { - final int lastPos = size - 1; - char lastChar = mTypedWord.charAt(lastPos); - mCodes.remove(lastPos); - mTypedWord.deleteCharAt(lastPos); + mCodes.remove(size - 1); + // Note: mTypedWord.length() and mCodes.length differ when there are surrogate pairs + final int stringBuilderLength = mTypedWord.length(); + if (stringBuilderLength < size) { + throw new RuntimeException( + "In WordComposer: mCodes and mTypedWords have non-matching lengths"); + } + final int lastChar = mTypedWord.codePointBefore(stringBuilderLength); + if (Character.isSupplementaryCodePoint(lastChar)) { + mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength); + } else { + mTypedWord.deleteCharAt(stringBuilderLength - 1); + } if (Character.isUpperCase(lastChar)) mCapsCount--; } - if (size() == 0) { + // We may have deleted the last one. + if (0 == mCodes.size()) { mIsFirstCharCapitalized = false; } + if (mTrailingSingleQuotesCount > 0) { + --mTrailingSingleQuotesCount; + } else { + int i = mTypedWord.length(); + while (i > 0) { + i = mTypedWord.offsetByCodePoints(i, -1); + if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; + ++mTrailingSingleQuotesCount; + } + } + mAutoCorrection = null; } /** * Returns the word as it was typed, without any correction applied. - * @return the word that was typed so far + * @return the word that was typed so far. Never returns null. */ public String getTypedWord() { - if (size() == 0) { - return null; - } return mTypedWord.toString(); } @@ -179,6 +307,10 @@ public class WordComposer { return mIsFirstCharCapitalized; } + public int trailingSingleQuotesCount() { + return mTrailingSingleQuotesCount; + } + /** * Whether or not all of the user typed chars are upper case * @return true if all user typed chars are upper case, false otherwise @@ -194,7 +326,7 @@ public class WordComposer { return mCapsCount > 1; } - /** + /** * Saves the reason why the word is capitalized - whether it was automatic or * due to the user hitting shift in the middle of a sentence. * @param auto whether it was an automatic capitalization due to start of sentence @@ -210,4 +342,50 @@ public class WordComposer { public boolean isAutoCapitalized() { return mAutoCapitalized; } + + /** + * Sets the auto-correction for this word. + */ + public void setAutoCorrection(final CharSequence correction) { + mAutoCorrection = correction; + } + + /** + * @return the auto-correction for this word, or null if none. + */ + public CharSequence getAutoCorrectionOrNull() { + return mAutoCorrection; + } + + // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above. + public LastComposedWord commitWord(final int type, final String committedWord, + final int separatorCode) { + // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK + // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate + // the last composed word to ensure this does not happen. + final ArrayList<int[]> codes = mCodes; + final int[] xCoordinates = mXCoordinates; + final int[] yCoordinates = mYCoordinates; + mCodes = new ArrayList<int[]>(N); + mXCoordinates = new int[N]; + mYCoordinates = new int[N]; + final LastComposedWord lastComposedWord = new LastComposedWord(codes, + xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode); + if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD + && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) { + lastComposedWord.deactivate(); + } + mTypedWord.setLength(0); + mAutoCorrection = null; + return lastComposedWord; + } + + public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) { + mCodes = lastComposedWord.mCodes; + mXCoordinates = lastComposedWord.mXCoordinates; + mYCoordinates = lastComposedWord.mYCoordinates; + mTypedWord.setLength(0); + mTypedWord.append(lastComposedWord.mTypedWord); + mAutoCorrection = null; // This will be filled by the next call to updateSuggestion. + } } diff --git a/java/src/com/android/inputmethod/latin/XmlParseUtils.java b/java/src/com/android/inputmethod/latin/XmlParseUtils.java new file mode 100644 index 000000000..e14c71cb5 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 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.res.TypedArray; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +public class XmlParseUtils { + @SuppressWarnings("serial") + public static class ParseException extends XmlPullParserException { + public ParseException(String msg, XmlPullParser parser) { + super(msg + " at " + parser.getPositionDescription()); + } + } + + @SuppressWarnings("serial") + public static class IllegalStartTag extends ParseException { + public IllegalStartTag(XmlPullParser parser, String parent) { + super("Illegal start tag " + parser.getName() + " in " + parent, parser); + } + } + + @SuppressWarnings("serial") + public static class IllegalEndTag extends ParseException { + public IllegalEndTag(XmlPullParser parser, String parent) { + super("Illegal end tag " + parser.getName() + " in " + parent, parser); + } + } + + @SuppressWarnings("serial") + public static class IllegalAttribute extends ParseException { + public IllegalAttribute(XmlPullParser parser, String attribute) { + super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser); + } + } + + @SuppressWarnings("serial") + public static class NonEmptyTag extends ParseException{ + public NonEmptyTag(String tag, XmlPullParser parser) { + super(tag + " must be empty tag", parser); + } + } + + public static void checkEndTag(String tag, XmlPullParser parser) + throws XmlPullParserException, IOException { + if (parser.next() == XmlPullParser.END_TAG && tag.equals(parser.getName())) + return; + throw new NonEmptyTag(tag, parser); + } + + public static void checkAttributeExists(TypedArray attr, int attrId, String attrName, + String tag, XmlPullParser parser) throws XmlPullParserException { + if (attr.hasValue(attrId)) + return; + throw new ParseException( + "No " + attrName + " attribute found in <" + tag + "/>", parser); + } +} diff --git a/java/src/com/android/inputmethod/latin/define/JniLibName.java b/java/src/com/android/inputmethod/latin/define/JniLibName.java new file mode 100644 index 000000000..3e94a3c07 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 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.define; + +public class JniLibName { + public static final String JNI_LIB_NAME = "jni_latinime"; +} diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 095c2c51c..35a5c0f52 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -17,7 +17,9 @@ package com.android.inputmethod.latin.spellcheck; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Resources; +import android.preference.PreferenceManager; import android.service.textservice.SpellCheckerService; import android.text.TextUtils; import android.util.Log; @@ -25,25 +27,28 @@ import android.view.textservice.SuggestionsInfo; import android.view.textservice.TextInfo; import com.android.inputmethod.compat.ArraysCompatUtils; +import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.Dictionary.DataType; import com.android.inputmethod.latin.Dictionary.WordCallback; import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; import com.android.inputmethod.latin.Flag; import com.android.inputmethod.latin.LocaleUtils; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SynchronouslyLoadedContactsDictionary; import com.android.inputmethod.latin.SynchronouslyLoadedUserDictionary; -import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.WhitelistDictionary; import com.android.inputmethod.latin.WordComposer; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.TreeMap; @@ -51,11 +56,14 @@ import java.util.TreeMap; /** * Service for spell checking, using LatinIME's dictionaries and mechanisms. */ -public class AndroidSpellCheckerService extends SpellCheckerService { +public class AndroidSpellCheckerService extends SpellCheckerService + implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = AndroidSpellCheckerService.class.getSimpleName(); private static final boolean DBG = false; private static final int POOL_SIZE = 2; + public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts"; + private static final int CAPITALIZE_NONE = 0; // No caps, or mixed case private static final int CAPITALIZE_FIRST = 1; // First only private static final int CAPITALIZE_ALL = 2; // All caps @@ -82,15 +90,100 @@ public class AndroidSpellCheckerService extends SpellCheckerService { // The threshold for a candidate to be offered as a suggestion. private double mSuggestionThreshold; - // The threshold for a suggestion to be considered "likely". - private double mLikelyThreshold; + // The threshold for a suggestion to be considered "recommended". + private double mRecommendedThreshold; + // Whether to use the contacts dictionary + private boolean mUseContactsDictionary; + private final Object mUseContactsLock = new Object(); + + private final HashSet<WeakReference<DictionaryCollection>> mDictionaryCollectionsList = + new HashSet<WeakReference<DictionaryCollection>>(); + + public static final int SCRIPT_LATIN = 0; + public static final int SCRIPT_CYRILLIC = 1; + private static final TreeMap<String, Integer> mLanguageToScript; + static { + // List of the supported languages and their associated script. We won't check + // words written in another script than the selected script, because we know we + // don't have those in our dictionary so we will underline everything and we + // will never have any suggestions, so it makes no sense checking them. + mLanguageToScript = new TreeMap<String, Integer>(); + mLanguageToScript.put("en", SCRIPT_LATIN); + mLanguageToScript.put("fr", SCRIPT_LATIN); + mLanguageToScript.put("de", SCRIPT_LATIN); + mLanguageToScript.put("nl", SCRIPT_LATIN); + mLanguageToScript.put("cs", SCRIPT_LATIN); + mLanguageToScript.put("es", SCRIPT_LATIN); + mLanguageToScript.put("it", SCRIPT_LATIN); + mLanguageToScript.put("ru", SCRIPT_CYRILLIC); + } @Override public void onCreate() { super.onCreate(); mSuggestionThreshold = Double.parseDouble(getString(R.string.spellchecker_suggestion_threshold_value)); - mLikelyThreshold = - Double.parseDouble(getString(R.string.spellchecker_likely_threshold_value)); + mRecommendedThreshold = + Double.parseDouble(getString(R.string.spellchecker_recommended_threshold_value)); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + prefs.registerOnSharedPreferenceChangeListener(this); + onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY); + } + + private static int getScriptFromLocale(final Locale locale) { + final Integer script = mLanguageToScript.get(locale.getLanguage()); + if (null == script) { + throw new RuntimeException("We have been called with an unsupported language: \"" + + locale.getLanguage() + "\". Framework bug?"); + } + return script; + } + + @Override + public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { + if (!PREF_USE_CONTACTS_KEY.equals(key)) return; + synchronized(mUseContactsLock) { + mUseContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true); + if (mUseContactsDictionary) { + startUsingContactsDictionaryLocked(); + } else { + stopUsingContactsDictionaryLocked(); + } + } + } + + private void startUsingContactsDictionaryLocked() { + if (null == mContactsDictionary) { + mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this); + } + final Iterator<WeakReference<DictionaryCollection>> iterator = + mDictionaryCollectionsList.iterator(); + while (iterator.hasNext()) { + final WeakReference<DictionaryCollection> dictRef = iterator.next(); + final DictionaryCollection dict = dictRef.get(); + if (null == dict) { + iterator.remove(); + } else { + dict.addDictionary(mContactsDictionary); + } + } + } + + private void stopUsingContactsDictionaryLocked() { + if (null == mContactsDictionary) return; + final SynchronouslyLoadedContactsDictionary contactsDict = mContactsDictionary; + mContactsDictionary = null; + final Iterator<WeakReference<DictionaryCollection>> iterator = + mDictionaryCollectionsList.iterator(); + while (iterator.hasNext()) { + final WeakReference<DictionaryCollection> dictRef = iterator.next(); + final DictionaryCollection dict = dictRef.get(); + if (null == dict) { + iterator.remove(); + } else { + dict.removeDictionary(contactsDict); + } + } + contactsDict.close(); } @Override @@ -110,10 +203,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private static class SuggestionsGatherer implements WordCallback { public static class Result { public final String[] mSuggestions; - public final boolean mHasLikelySuggestions; - public Result(final String[] gatheredSuggestions, final boolean hasLikelySuggestions) { + public final boolean mHasRecommendedSuggestions; + public Result(final String[] gatheredSuggestions, + final boolean hasRecommendedSuggestions) { mSuggestions = gatheredSuggestions; - mHasLikelySuggestions = hasLikelySuggestions; + mHasRecommendedSuggestions = hasRecommendedSuggestions; } } @@ -121,7 +215,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private final int[] mScores; private final String mOriginalText; private final double mSuggestionThreshold; - private final double mLikelyThreshold; + private final double mRecommendedThreshold; private final int mMaxLength; private int mLength = 0; @@ -131,10 +225,10 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private int mBestScore = Integer.MIN_VALUE; // As small as possible SuggestionsGatherer(final String originalText, final double suggestionThreshold, - final double likelyThreshold, final int maxLength) { + final double recommendedThreshold, final int maxLength) { mOriginalText = originalText; mSuggestionThreshold = suggestionThreshold; - mLikelyThreshold = likelyThreshold; + mRecommendedThreshold = recommendedThreshold; mMaxLength = maxLength; mSuggestions = new ArrayList<CharSequence>(maxLength + 1); mScores = new int[mMaxLength]; @@ -142,7 +236,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { @Override synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, - int dicTypeId, DataType dataType) { + int dicTypeId, int dataType) { final int positionIndex = ArraysCompatUtils.binarySearch(mScores, 0, mLength, score); // binarySearch returns the index if the element exists, and -<insertion index> - 1 // if it doesn't. See documentation for binarySearch. @@ -175,7 +269,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { // make the threshold. final String wordString = new String(word, wordOffset, wordLength); final double normalizedScore = - Utils.calcNormalizedScore(mOriginalText, wordString, score); + BinaryDictionary.calcNormalizedScore(mOriginalText, wordString, score); if (normalizedScore < mSuggestionThreshold) { if (DBG) Log.i(TAG, wordString + " does not make the score threshold"); return true; @@ -198,19 +292,19 @@ public class AndroidSpellCheckerService extends SpellCheckerService { public Result getResults(final int capitalizeType, final Locale locale) { final String[] gatheredSuggestions; - final boolean hasLikelySuggestions; + final boolean hasRecommendedSuggestions; if (0 == mLength) { // Either we found no suggestions, or we found some BUT the max length was 0. // If we found some mBestSuggestion will not be null. If it is null, then // we found none, regardless of the max length. if (null == mBestSuggestion) { gatheredSuggestions = null; - hasLikelySuggestions = false; + hasRecommendedSuggestions = false; } else { gatheredSuggestions = EMPTY_STRING_ARRAY; - final double normalizedScore = - Utils.calcNormalizedScore(mOriginalText, mBestSuggestion, mBestScore); - hasLikelySuggestions = (normalizedScore > mLikelyThreshold); + final double normalizedScore = BinaryDictionary.calcNormalizedScore( + mOriginalText, mBestSuggestion, mBestScore); + hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold); } } else { if (DBG) { @@ -222,7 +316,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { } } Collections.reverse(mSuggestions); - Utils.removeDupes(mSuggestions); + StringUtils.removeDupes(mSuggestions); if (CAPITALIZE_ALL == capitalizeType) { for (int i = 0; i < mSuggestions.size(); ++i) { // get(i) returns a CharSequence which is actually a String so .toString() @@ -232,7 +326,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { } else if (CAPITALIZE_FIRST == capitalizeType) { for (int i = 0; i < mSuggestions.size(); ++i) { // Likewise - mSuggestions.set(i, Utils.toTitleCase(mSuggestions.get(i).toString(), + mSuggestions.set(i, StringUtils.toTitleCase(mSuggestions.get(i).toString(), locale)); } } @@ -243,16 +337,17 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final int bestScore = mScores[mLength - 1]; final CharSequence bestSuggestion = mSuggestions.get(0); final double normalizedScore = - Utils.calcNormalizedScore(mOriginalText, bestSuggestion, bestScore); - hasLikelySuggestions = (normalizedScore > mLikelyThreshold); + BinaryDictionary.calcNormalizedScore( + mOriginalText, bestSuggestion.toString(), bestScore); + hasRecommendedSuggestions = (normalizedScore > mRecommendedThreshold); if (DBG) { Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore); Log.i(TAG, "Normalized score = " + normalizedScore - + " (threshold " + mLikelyThreshold - + ") => hasLikelySuggestions = " + hasLikelySuggestions); + + " (threshold " + mRecommendedThreshold + + ") => hasRecommendedSuggestions = " + hasRecommendedSuggestions); } } - return new Result(gatheredSuggestions, hasLikelySuggestions); + return new Result(gatheredSuggestions, hasRecommendedSuggestions); } } @@ -273,13 +368,15 @@ public class AndroidSpellCheckerService extends SpellCheckerService { for (Dictionary dict : oldWhitelistDictionaries.values()) { dict.close(); } - if (null != mContactsDictionary) { - // The synchronously loaded contacts dictionary should have been in one - // or several pools, but it is shielded against multiple closing and it's - // safe to call it several times. - final SynchronouslyLoadedContactsDictionary dictToClose = mContactsDictionary; - mContactsDictionary = null; - dictToClose.close(); + synchronized(mUseContactsLock) { + if (null != mContactsDictionary) { + // The synchronously loaded contacts dictionary should have been in one + // or several pools, but it is shielded against multiple closing and it's + // safe to call it several times. + final SynchronouslyLoadedContactsDictionary dictToClose = mContactsDictionary; + mContactsDictionary = null; + dictToClose.close(); + } } return false; } @@ -295,9 +392,11 @@ public class AndroidSpellCheckerService extends SpellCheckerService { } public DictAndProximity createDictAndProximity(final Locale locale) { - final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo(); + final int script = getScriptFromLocale(locale); + final ProximityInfo proximityInfo = ProximityInfo.createSpellCheckerProximityInfo( + SpellCheckerProximityInfo.getProximityForScript(script)); final Resources resources = getResources(); - final int fallbackResourceId = Utils.getMainDictionaryResourceId(resources); + final int fallbackResourceId = DictionaryFactory.getMainDictionaryResourceId(resources); final DictionaryCollection dictionaryCollection = DictionaryFactory.createDictionaryFromManager(this, locale, fallbackResourceId, USE_FULL_EDIT_DISTANCE_FLAG_ARRAY); @@ -314,11 +413,16 @@ public class AndroidSpellCheckerService extends SpellCheckerService { mWhitelistDictionaries.put(localeStr, whitelistDictionary); } dictionaryCollection.addDictionary(whitelistDictionary); - if (null == mContactsDictionary) { - mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this); + synchronized(mUseContactsLock) { + if (mUseContactsDictionary) { + if (null == mContactsDictionary) { + mContactsDictionary = new SynchronouslyLoadedContactsDictionary(this); + } + } + dictionaryCollection.addDictionary(mContactsDictionary); + mDictionaryCollectionsList.add( + new WeakReference<DictionaryCollection>(dictionaryCollection)); } - // TODO: add a setting to use or not contacts when checking spelling - dictionaryCollection.addDictionary(mContactsDictionary); return new DictAndProximity(dictionaryCollection, proximityInfo); } @@ -327,9 +431,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService { // If the first char is not uppercase, then the word is either all lower case, // and in either case we return CAPITALIZE_NONE. if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE; - final int len = text.codePointCount(0, text.length()); + final int len = text.length(); int capsCount = 1; - for (int i = 1; i < len; ++i) { + for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) { if (1 != capsCount && i != capsCount) break; if (Character.isUpperCase(text.codePointAt(i))) ++capsCount; } @@ -346,6 +450,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService { private DictionaryPool mDictionaryPool; // Likewise private Locale mLocale; + // Cache this for performance + private int mScript; // One of SCRIPT_LATIN or SCRIPT_CYRILLIC for now. private final AndroidSpellCheckerService mService; @@ -358,17 +464,51 @@ public class AndroidSpellCheckerService extends SpellCheckerService { final String localeString = getLocale(); mDictionaryPool = mService.getDictionaryPool(localeString); mLocale = LocaleUtils.constructLocaleFromString(localeString); + mScript = getScriptFromLocale(mLocale); + } + + /* + * Returns whether the code point is a letter that makes sense for the specified + * locale for this spell checker. + * The dictionaries supported by Latin IME are described in res/xml/spellchecker.xml + * and is limited to EFIGS languages and Russian. + * Hence at the moment this explicitly tests for Cyrillic characters or Latin characters + * as appropriate, and explicitly excludes CJK, Arabic and Hebrew characters. + */ + private static boolean isLetterCheckableByLanguage(final int codePoint, + final int script) { + switch (script) { + case SCRIPT_LATIN: + // Our supported latin script dictionaries (EFIGS) at the moment only include + // characters in the C0, C1, Latin Extended A and B, IPA extensions unicode + // blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF, + // so the below is a very efficient way to test for it. As for the 0-0x3F, it's + // excluded from isLetter anyway. + return codePoint <= 0x2AF && Character.isLetter(codePoint); + case SCRIPT_CYRILLIC: + // All Cyrillic characters are in the 400~52F block. There are some in the upper + // Unicode range, but they are archaic characters that are not used in modern + // russian and are not used by our dictionary. + return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint); + default: + // Should never come here + throw new RuntimeException("Impossible value of script: " + script); + } } /** * Finds out whether a particular string should be filtered out of spell checking. * - * This will loosely match URLs, numbers, symbols. + * This will loosely match URLs, numbers, symbols. To avoid always underlining words that + * we know we will never recognize, this accepts a script identifier that should be one + * of the SCRIPT_* constants defined above, to rule out quickly characters from very + * different languages. * * @param text the string to evaluate. + * @param script the identifier for the script this spell checker recognizes * @return true if we should filter this text out, false otherwise */ - private boolean shouldFilterOut(final String text) { + private static boolean shouldFilterOut(final String text, final int script) { if (TextUtils.isEmpty(text) || text.length() <= 1) return true; // TODO: check if an equivalent processing can't be done more quickly with a @@ -376,20 +516,19 @@ public class AndroidSpellCheckerService extends SpellCheckerService { // Filter by first letter final int firstCodePoint = text.codePointAt(0); // Filter out words that don't start with a letter or an apostrophe - if (!Character.isLetter(firstCodePoint) + if (!isLetterCheckableByLanguage(firstCodePoint, script) && '\'' != firstCodePoint) return true; // Filter contents final int length = text.length(); int letterCount = 0; - for (int i = 0; i < length; ++i) { + for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { final int codePoint = text.codePointAt(i); // Any word containing a '@' is probably an e-mail address // Any word containing a '/' is probably either an ad-hoc combination of two // words or a URI - in either case we don't want to spell check that - if ('@' == codePoint - || '/' == codePoint) return true; - if (Character.isLetter(codePoint)) ++letterCount; + if ('@' == codePoint || '/' == codePoint) return true; + if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount; } // Guestimate heuristic: perform spell checking if at least 3/4 of the characters // in this word are letters @@ -408,7 +547,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { try { final String text = textInfo.getText(); - if (shouldFilterOut(text)) { + if (shouldFilterOut(text, mScript)) { DictAndProximity dictInfo = null; try { dictInfo = mDictionaryPool.takeOrGetNull(); @@ -426,22 +565,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService { // TODO: Don't gather suggestions if the limit is <= 0 unless necessary final SuggestionsGatherer suggestionsGatherer = new SuggestionsGatherer(text, - mService.mSuggestionThreshold, mService.mLikelyThreshold, suggestionsLimit); + mService.mSuggestionThreshold, mService.mRecommendedThreshold, + suggestionsLimit); final WordComposer composer = new WordComposer(); final int length = text.length(); - for (int i = 0; i < length; ++i) { - final int character = text.codePointAt(i); - final int proximityIndex = SpellCheckerProximityInfo.getIndexOf(character); - final int[] proximities; - if (-1 == proximityIndex) { - proximities = new int[] { character }; - } else { - proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY, - proximityIndex, - proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); - } - composer.add(character, proximities, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { + composer.addKeyForSpellChecker(text.codePointAt(i), mScript); } final int capitalizeType = getCapitalizationType(text); @@ -475,7 +604,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService { + suggestionsLimit); Log.i(TAG, "IsInDict = " + isInDict); Log.i(TAG, "LooksLikeTypo = " + (!isInDict)); - Log.i(TAG, "HasLikelySuggestions = " + result.mHasLikelySuggestions); + Log.i(TAG, "HasRecommendedSuggestions = " + result.mHasRecommendedSuggestions); if (null != result.mSuggestions) { for (String suggestion : result.mSuggestions) { Log.i(TAG, suggestion); @@ -483,10 +612,13 @@ public class AndroidSpellCheckerService extends SpellCheckerService { } } - // TODO: actually use result.mHasLikelySuggestions final int flags = (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY - : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO); + : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) + | (result.mHasRecommendedSuggestions + ? SuggestionsInfoCompatUtils + .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS() + : 0); return new SuggestionsInfo(flags, result.mSuggestions); } catch (RuntimeException e) { // Don't kill the keyboard if there is a bug in the spell checker diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java index d5b04b27c..db3544987 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -22,72 +22,158 @@ import com.android.inputmethod.keyboard.ProximityInfo; import java.util.TreeMap; public class SpellCheckerProximityInfo { - final private static int NUL = KeyDetector.NOT_A_CODE; + /* public for test */ + final public static int NUL = KeyDetector.NOT_A_CODE; // This must be the same as MAX_PROXIMITY_CHARS_SIZE else it will not work inside // native code - this value is passed at creation of the binary object and reused // as the size of the passed array afterwards so they can't be different. final public static int ROW_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE; - // This is a map from the code point to the index in the PROXIMITY array. - // At the time the native code to read the binary dictionary needs the proximity info be passed - // as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input character. - // Since we need to build such an array, we want to be able to search in our big proximity data - // quickly by character, and a map is probably the best way to do this. - final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>(); + // Helper methods + final protected static void buildProximityIndices(final int[] proximity, + final TreeMap<Integer, Integer> indices) { + for (int i = 0; i < proximity.length; i += ROW_SIZE) { + if (NUL != proximity[i]) indices.put(proximity[i], i); + } + } + final protected static int computeIndex(final int characterCode, + final TreeMap<Integer, Integer> indices) { + final Integer result = indices.get(characterCode); + if (null == result) return -1; + return result; + } - // The proximity here is the union of - // - the proximity for a QWERTY keyboard. - // - the proximity for an AZERTY keyboard. - // - the proximity for a QWERTZ keyboard. - // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other. - // - // The reasoning behind this construction is, almost any alphabetic text we may want - // to spell check has been entered with one of the keyboards above. Also, specifically - // to English, many spelling errors consist of the last vowel of the word being wrong - // because in English vowels tend to merge with each other in pronunciation. - final public static int[] PROXIMITY = { - 'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL, - 'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL, - 'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + private static class Latin { + // This is a map from the code point to the index in the PROXIMITY array. + // At the time the native code to read the binary dictionary needs the proximity info be + // passed as a flat array spaced by MAX_PROXIMITY_CHARS_SIZE columns, one for each input + // character. + // Since we need to build such an array, we want to be able to search in our big proximity + // data quickly by character, and a map is probably the best way to do this. + final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>(); - 'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL, - 's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, - 'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + // The proximity here is the union of + // - the proximity for a QWERTY keyboard. + // - the proximity for an AZERTY keyboard. + // - the proximity for a QWERTZ keyboard. + // ...plus, add all characters in the ('a', 'e', 'i', 'o', 'u') set to each other. + // + // The reasoning behind this construction is, almost any alphabetic text we may want + // to spell check has been entered with one of the keyboards above. Also, specifically + // to English, many spelling errors consist of the last vowel of the word being wrong + // because in English vowels tend to merge with each other in pronunciation. + final static int[] PROXIMITY = { + 'q', 'w', 's', 'a', 'z', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'w', 'q', 'a', 's', 'd', 'e', 'x', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'e', 'w', 's', 'd', 'f', 'r', 'a', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL, + 'r', 'e', 'd', 'f', 'g', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 't', 'r', 'f', 'g', 'h', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'y', 't', 'g', 'h', 'j', 'u', 'a', 's', 'd', 'x', NUL, NUL, NUL, NUL, NUL, NUL, + 'u', 'y', 'h', 'j', 'k', 'i', 'a', 'e', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'i', 'u', 'j', 'k', 'l', 'o', 'a', 'e', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'o', 'i', 'k', 'l', 'p', 'a', 'e', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'p', 'o', 'l', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL, - 'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - 'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, - }; - static { - for (int i = 0; i < PROXIMITY.length; i += ROW_SIZE) { - if (NUL != PROXIMITY[i]) INDICES.put(PROXIMITY[i], i); + 'a', 'z', 'x', 's', 'w', 'q', 'e', 'i', 'o', 'u', NUL, NUL, NUL, NUL, NUL, NUL, + 's', 'q', 'a', 'z', 'x', 'c', 'd', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'd', 'w', 's', 'x', 'c', 'v', 'f', 'r', 'e', 'w', NUL, NUL, NUL, NUL, NUL, NUL, + 'f', 'e', 'd', 'c', 'v', 'b', 'g', 't', 'r', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'g', 'r', 'f', 'v', 'b', 'n', 'h', 'y', 't', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'h', 't', 'g', 'b', 'n', 'm', 'j', 'u', 'y', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'j', 'y', 'h', 'n', 'm', 'k', 'i', 'u', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'k', 'u', 'j', 'm', 'l', 'o', 'i', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'l', 'i', 'k', 'p', 'o', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + + 'z', 'a', 's', 'd', 'x', 't', 'g', 'h', 'j', 'u', 'q', 'e', NUL, NUL, NUL, NUL, + 'x', 'z', 'a', 's', 'd', 'c', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'c', 'x', 's', 'd', 'f', 'v', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'v', 'c', 'd', 'f', 'g', 'b', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'b', 'v', 'f', 'g', 'h', 'n', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'n', 'b', 'g', 'h', 'j', 'm', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'm', 'n', 'h', 'j', 'k', 'l', 'o', 'p', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + }; + static { + buildProximityIndices(PROXIMITY, INDICES); + } + static int getIndexOf(int characterCode) { + return computeIndex(characterCode, INDICES); } } - public static int getIndexOf(int characterCode) { - final Integer result = INDICES.get(characterCode); - if (null == result) return -1; - return result; + + private static class Cyrillic { + final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>(); + final static int[] PROXIMITY = { + // TODO: This table is solely based on the keyboard layout. Consult with Russian + // speakers on commonly misspelled words/letters. + 'й', 'ц', 'ф', 'ы', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ц', 'й', 'ф', 'ы', 'в', 'у', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'у', 'ц', 'ы', 'в', 'а', 'к', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'к', 'у', 'в', 'а', 'п', 'е', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'е', 'к', 'а', 'п', 'р', 'н', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'н', 'е', 'п', 'р', 'о', 'г', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'г', 'н', 'р', 'о', 'л', 'ш', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ш', 'г', 'о', 'л', 'д', 'щ', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'щ', 'ш', 'л', 'д', 'ж', 'з', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'з', 'щ', 'д', 'ж', 'э', 'х', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'х', 'з', 'ж', 'э', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + + 'ф', 'й', 'ц', 'ы', 'я', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ы', 'й', 'ц', 'у', 'ф', 'в', 'я', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'в', 'ц', 'у', 'к', 'ы', 'а', 'я', 'ч', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'а', 'у', 'к', 'е', 'в', 'п', 'ч', 'с', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'п', 'к', 'е', 'н', 'а', 'р', 'с', 'м', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'р', 'е', 'н', 'г', 'п', 'о', 'м', 'и', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'о', 'н', 'г', 'ш', 'р', 'л', 'и', 'т', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'л', 'г', 'ш', 'щ', 'о', 'д', 'т', 'ь', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'д', 'ш', 'щ', 'з', 'л', 'ж', 'ь', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ж', 'щ', 'з', 'х', 'д', 'э', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'э', 'з', 'х', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + + 'я', 'ф', 'ы', 'в', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ч', 'ы', 'в', 'а', 'я', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'с', 'в', 'а', 'п', 'ч', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'м', 'а', 'п', 'р', 'с', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'и', 'п', 'р', 'о', 'м', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'т', 'р', 'о', 'л', 'и', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ь', 'о', 'л', 'д', 'т', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'б', 'л', 'д', 'ж', 'ь', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ю', 'д', 'ж', 'э', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + }; + static { + buildProximityIndices(PROXIMITY, INDICES); + } + static int getIndexOf(int characterCode) { + return computeIndex(characterCode, INDICES); + } + } + + public static int[] getProximityForScript(final int script) { + switch (script) { + case AndroidSpellCheckerService.SCRIPT_LATIN: + return Latin.PROXIMITY; + case AndroidSpellCheckerService.SCRIPT_CYRILLIC: + return Cyrillic.PROXIMITY; + default: + throw new RuntimeException("Wrong script supplied: " + script); + } + } + public static int getIndexOfCodeForScript(final int characterCode, final int script) { + switch (script) { + case AndroidSpellCheckerService.SCRIPT_LATIN: + return Latin.getIndexOf(characterCode); + case AndroidSpellCheckerService.SCRIPT_CYRILLIC: + return Cyrillic.getIndexOf(characterCode); + default: + throw new RuntimeException("Wrong script supplied: " + script); + } } } diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 9a59ef2e0..c9c88fd23 100644 --- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -14,37 +14,38 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.suggestions; import android.content.res.Resources; import android.graphics.Paint; import android.graphics.drawable.Drawable; -import android.text.TextUtils; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.internal.KeyboardBuilder; -import com.android.inputmethod.keyboard.internal.KeyboardParams; -import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SuggestedWords; +import com.android.inputmethod.latin.Utils; public class MoreSuggestions extends Keyboard { - private static final boolean DBG = LatinImeLogger.sDBG; - public static final int SUGGESTION_CODE_BASE = 1024; - private MoreSuggestions(Builder.MoreSuggestionsParam params) { + MoreSuggestions(Builder.MoreSuggestionsParam params) { super(params); } - public static class Builder extends KeyboardBuilder<Builder.MoreSuggestionsParam> { + public static class Builder extends Keyboard.Builder<Builder.MoreSuggestionsParam> { + private static final boolean DBG = LatinImeLogger.sDBG; + private final MoreSuggestionsView mPaneView; private SuggestedWords mSuggestions; private int mFromPos; private int mToPos; - public static class MoreSuggestionsParam extends KeyboardParams { + public static class MoreSuggestionsParam extends Keyboard.Params { private final int[] mWidths = new int[SuggestionsView.MAX_SUGGESTIONS]; private final int[] mRowNumbers = new int[SuggestionsView.MAX_SUGGESTIONS]; private final int[] mColumnOrders = new int[SuggestionsView.MAX_SUGGESTIONS]; @@ -61,7 +62,7 @@ public class MoreSuggestions extends Keyboard { paint.setAntiAlias(true); final Resources res = view.getContext().getResources(); mDivider = res.getDrawable(R.drawable.more_suggestions_divider); - // TODO: Drawable itself should has an alpha value. + // TODO: Drawable itself should have an alpha value. mDivider.setAlpha(128); mDividerWidth = mDivider.getIntrinsicWidth(); final int padding = (int) res.getDimension( @@ -71,7 +72,7 @@ public class MoreSuggestions extends Keyboard { int pos = fromPos, rowStartPos = fromPos; final int size = Math.min(suggestions.size(), SuggestionsView.MAX_SUGGESTIONS); while (pos < size) { - final CharSequence word = suggestions.getWord(pos); + final String word = suggestions.getWord(pos).toString(); // TODO: Should take care of text x-scaling. mWidths[pos] = (int)view.getDefaultLabelWidth(word, paint) + padding; final int numColumn = pos - rowStartPos + 1; @@ -176,9 +177,9 @@ public class MoreSuggestions extends Keyboard { public Builder layout(SuggestedWords suggestions, int fromPos, int maxWidth, int minWidth, int maxRow) { - final Keyboard keyboard = KeyboardSwitcher.getInstance().getLatinKeyboard(); + final Keyboard keyboard = KeyboardSwitcher.getInstance().getKeyboard(); final int xmlId = R.xml.kbd_suggestions_pane_template; - load(keyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId)); + load(xmlId, keyboard.mId); mParams.mVerticalGap = mParams.mTopPadding = keyboard.mVerticalGap / 2; final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow, @@ -189,13 +190,19 @@ public class MoreSuggestions extends Keyboard { return this; } - private static String getDebugInfo(SuggestedWords suggestions, int pos) { - if (!DBG) return null; - final SuggestedWordInfo wordInfo = suggestions.getInfo(pos); - if (wordInfo == null) return null; - final String info = wordInfo.getDebugString(); - if (TextUtils.isEmpty(info)) return null; - return info; + private static class Divider extends Key.Spacer { + private final Drawable mIcon; + + public Divider(Keyboard.Params params, Drawable icon, int x, int y, int width, + int height) { + super(params, x, y, width, height); + mIcon = icon; + } + + @Override + public Drawable getIcon(KeyboardIconsSet iconSet) { + return mIcon; + } } @Override @@ -206,19 +213,19 @@ public class MoreSuggestions extends Keyboard { final int y = params.getY(pos); final int width = params.getWidth(pos); final String word = mSuggestions.getWord(pos).toString(); - final String info = getDebugInfo(mSuggestions, pos); + final String info = Utils.getDebugInfo(mSuggestions, pos); final int index = pos + SUGGESTION_CODE_BASE; final Key key = new Key( - params, word, info, null, index, null, x, y, width, - params.mDefaultRowHeight); + params, word, info, KeyboardIconsSet.ICON_UNDEFINED, index, null, x, y, + width, params.mDefaultRowHeight, 0); params.markAsEdgeKey(key, pos); params.onAddKey(key); final int columnNumber = params.getColumnNumber(pos); final int numColumnInRow = params.getNumColumnInRow(pos); if (columnNumber < numColumnInRow - 1) { - final Key.Spacer spacer = new Key.Spacer(params, params.mDivider, x + width, y, + final Divider divider = new Divider(params, params.mDivider, x + width, y, params.mDividerWidth, params.mDefaultRowHeight); - params.onAddKey(spacer); + params.onAddKey(divider); } } return new MoreSuggestions(params); diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index 8eab79413..f11b1a4c1 100644 --- a/java/src/com/android/inputmethod/latin/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.suggestions; import android.content.Context; import android.content.res.Resources; @@ -34,6 +34,7 @@ import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; +import com.android.inputmethod.latin.R; /** * A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting @@ -55,17 +56,17 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { private final KeyboardActionListener mSuggestionsPaneListener = new KeyboardActionListener.Adapter() { @Override - public void onPress(int primaryCode, boolean withSliding) { - mListener.onPress(primaryCode, withSliding); + public void onPressKey(int primaryCode) { + mListener.onPressKey(primaryCode); } @Override - public void onRelease(int primaryCode, boolean withSliding) { - mListener.onRelease(primaryCode, withSliding); + public void onReleaseKey(int primaryCode, boolean withSliding) { + mListener.onReleaseKey(primaryCode, withSliding); } @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE; if (index >= 0 && index < SuggestionsView.MAX_SUGGESTIONS) { mListener.onCustomRequest(index); @@ -140,11 +141,6 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { } @Override - public void setShifted(boolean shifted) { - // Nothing to do with. - } - - @Override public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY, PopupWindow window, KeyboardActionListener listener) { mController = controller; diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index c25ecb382..d3c3afb73 100644 --- a/java/src/com/android/inputmethod/latin/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.suggestions; import android.content.Context; import android.content.res.Resources; @@ -30,7 +30,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Message; -import android.os.SystemClock; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; @@ -58,7 +57,13 @@ import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.PointerTracker; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.StaticInnerHandlerWrapper; +import com.android.inputmethod.latin.Suggest; +import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.Utils; import java.util.ArrayList; import java.util.List; @@ -73,7 +78,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. public static final int MAX_SUGGESTIONS = 18; - private static final boolean DBG = LatinImeLogger.sDBG; + static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mSuggestionsStrip; private KeyboardView mKeyboardView; @@ -91,7 +96,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, private final TextView mPreviewText; private Listener mListener; - private SuggestedWords mSuggestions = SuggestedWords.EMPTY; + private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; private final SuggestionsViewParams mParams; private static final float MIN_TEXT_XSCALE = 0.70f; @@ -101,8 +106,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, private static class UiHandler extends StaticInnerHandlerWrapper<SuggestionsView> { private static final int MSG_HIDE_PREVIEW = 0; - private static final long DELAY_HIDE_PREVIEW = 1300; - public UiHandler(SuggestionsView outerInstance) { super(outerInstance); } @@ -117,11 +120,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } } - public void postHidePreview() { - cancelHidePreview(); - sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW); - } - public void cancelHidePreview() { removeMessages(MSG_HIDE_PREVIEW); } @@ -141,7 +139,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public final int mDividerWidth; public final int mSuggestionsStripHeight; public final int mSuggestionsCountInStrip; - public final int mMaxMoreSuggestionsRow; + public final int mMoreSuggestionsRowHeight; + private int mMaxMoreSuggestionsRow; public final float mMinMoreSuggestionsWidth; public final int mMoreSuggestionsBottomGap; @@ -149,6 +148,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, private final List<View> mDividers; private final List<TextView> mInfos; + private final int mColorValidTypedWord; private final int mColorTypedWord; private final int mColorAutoCorrect; private final int mColorSuggested; @@ -172,7 +172,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public final TextView mWordToSaveView; private final TextView mHintToSaveView; - private final CharSequence mHintToSaveText; public SuggestionsViewParams(Context context, AttributeSet attrs, int defStyle, List<TextView> words, List<View> dividers, List<TextView> infos) { @@ -193,6 +192,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.SuggestionsView, defStyle, R.style.SuggestionsViewStyle); mSuggestionStripOption = a.getInt(R.styleable.SuggestionsView_suggestionStripOption, 0); + final float alphaValidTypedWord = getPercent(a, + R.styleable.SuggestionsView_alphaValidTypedWord, 100); final float alphaTypedWord = getPercent(a, R.styleable.SuggestionsView_alphaTypedWord, 100); final float alphaAutoCorrect = getPercent(a, @@ -200,6 +201,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final float alphaSuggested = getPercent(a, R.styleable.SuggestionsView_alphaSuggested, 100); mAlphaObsoleted = getPercent(a, R.styleable.SuggestionsView_alphaSuggested, 100); + mColorValidTypedWord = applyAlpha( + a.getColor(R.styleable.SuggestionsView_colorValidTypedWord, 0), + alphaValidTypedWord); mColorTypedWord = applyAlpha( a.getColor(R.styleable.SuggestionsView_colorTypedWord, 0), alphaTypedWord); mColorAutoCorrect = applyAlpha( @@ -224,11 +228,32 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, mCenterSuggestionIndex = mSuggestionsCountInStrip / 2; mMoreSuggestionsBottomGap = res.getDimensionPixelOffset( R.dimen.more_suggestions_bottom_gap); + mMoreSuggestionsRowHeight = res.getDimensionPixelSize( + R.dimen.more_suggestions_row_height); final LayoutInflater inflater = LayoutInflater.from(context); mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null); mHintToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null); - mHintToSaveText = context.getText(R.string.hint_add_to_dictionary); + } + + public int getMaxMoreSuggestionsRow() { + return mMaxMoreSuggestionsRow; + } + + private int getMoreSuggestionsHeight() { + return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap; + } + + public int setMoreSuggestionsHeight(int remainingHeight) { + final int currentHeight = getMoreSuggestionsHeight(); + if (currentHeight <= remainingHeight) { + return currentHeight; + } + + mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap) + / mMoreSuggestionsRowHeight; + final int newHeight = getMoreSuggestionsHeight(); + return newHeight; } private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) { @@ -258,10 +283,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, return a.getFraction(index, 1000, 1000, 1) / 1000.0f; } - private CharSequence getStyledSuggestionWord(SuggestedWords suggestions, int pos) { - final CharSequence word = suggestions.getWord(pos); - final boolean isAutoCorrect = pos == 1 && Utils.willAutoCorrect(suggestions); - final boolean isTypedWordValid = pos == 0 && suggestions.mTypedWordValid; + private CharSequence getStyledSuggestionWord(SuggestedWords suggestedWords, int pos) { + final CharSequence word = suggestedWords.getWord(pos); + final boolean isAutoCorrect = pos == 1 && suggestedWords.willAutoCorrect(); + final boolean isTypedWordValid = pos == 0 && suggestedWords.mTypedWordValid; if (!isAutoCorrect && !isTypedWordValid) return word; @@ -278,10 +303,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, return spannedWord; } - private int getWordPosition(int index, SuggestedWords suggestions) { + private int getWordPosition(int index, SuggestedWords suggestedWords) { // TODO: This works for 3 suggestions. Revisit this algorithm when there are 5 or more // suggestions. - final int centerPos = Utils.willAutoCorrect(suggestions) ? 1 : 0; + final int centerPos = suggestedWords.willAutoCorrect() ? 1 : 0; if (index == mCenterSuggestionIndex) { return centerPos; } else if (index == centerPos) { @@ -291,28 +316,31 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } } - private int getSuggestionTextColor(int index, SuggestedWords suggestions, int pos) { + private int getSuggestionTextColor(int index, SuggestedWords suggestedWords, int pos) { // TODO: Need to revisit this logic with bigram suggestions final boolean isSuggested = (pos != 0); final int color; - if (index == mCenterSuggestionIndex && Utils.willAutoCorrect(suggestions)) { + if (index == mCenterSuggestionIndex && suggestedWords.willAutoCorrect()) { color = mColorAutoCorrect; + } else if (index == mCenterSuggestionIndex && suggestedWords.mTypedWordValid) { + color = mColorValidTypedWord; } else if (isSuggested) { color = mColorSuggested; } else { color = mColorTypedWord; } - if (LatinImeLogger.sDBG) { - if (index == mCenterSuggestionIndex && suggestions.mHasAutoCorrectionCandidate - && suggestions.shouldBlockAutoCorrection()) { + if (LatinImeLogger.sDBG && suggestedWords.size() > 1) { + // If we auto-correct, then the autocorrection is in slot 0 and the typed word + // is in slot 1. + if (index == mCenterSuggestionIndex && suggestedWords.mHasAutoCorrectionCandidate + && Suggest.shouldBlockAutoCorrectionBySafetyNet( + suggestedWords.getWord(1).toString(), suggestedWords.getWord(0))) { return 0xFFFF0000; } } - final SuggestedWordInfo info = (pos < suggestions.size()) - ? suggestions.getInfo(pos) : null; - if (info != null && info.isObsoleteSuggestedWord()) { + if (suggestedWords.mIsObsoleteSuggestions && isSuggested) { return applyAlpha(color, mAlphaObsoleted); } else { return color; @@ -331,19 +359,19 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, params.gravity = Gravity.CENTER; } - public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, + public void layout(SuggestedWords suggestedWords, ViewGroup stripView, ViewGroup placer, int stripWidth) { - if (suggestions.isPunctuationSuggestions()) { - layoutPunctuationSuggestions(suggestions, stripView); + if (suggestedWords.mIsPunctuationSuggestions) { + layoutPunctuationSuggestions(suggestedWords, stripView); return; } final int countInStrip = mSuggestionsCountInStrip; - setupTexts(suggestions, countInStrip); - mMoreSuggestionsAvailable = (suggestions.size() > countInStrip); + setupTexts(suggestedWords, countInStrip); + mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); int x = 0; for (int index = 0; index < countInStrip; index++) { - final int pos = getWordPosition(index, suggestions); + final int pos = getWordPosition(index, suggestedWords); if (index != 0) { final View divider = mDividers.get(pos); @@ -366,7 +394,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, // Disable this suggestion if the suggestion is null or empty. word.setEnabled(!TextUtils.isEmpty(styled)); - word.setTextColor(getSuggestionTextColor(index, suggestions, pos)); + word.setTextColor(getSuggestionTextColor(index, suggestedWords, pos)); final int width = getSuggestionWidth(index, stripWidth); final CharSequence text = getEllipsizedText(styled, width, word.getPaint()); final float scaleX = word.getTextScaleX(); @@ -377,8 +405,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, word, getSuggestionWeight(index), ViewGroup.LayoutParams.MATCH_PARENT); x += word.getMeasuredWidth(); - if (DBG) { - final CharSequence debugInfo = getDebugInfo(suggestions, pos); + if (DBG && pos < suggestedWords.size()) { + final CharSequence debugInfo = Utils.getDebugInfo(suggestedWords, pos); if (debugInfo != null) { final TextView info = mInfos.get(pos); info.setText(debugInfo); @@ -410,11 +438,11 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } } - private void setupTexts(SuggestedWords suggestions, int countInStrip) { + private void setupTexts(SuggestedWords suggestedWords, int countInStrip) { mTexts.clear(); - final int count = Math.min(suggestions.size(), countInStrip); + final int count = Math.min(suggestedWords.size(), countInStrip); for (int pos = 0; pos < count; pos++) { - final CharSequence styled = getStyledSuggestionWord(suggestions, pos); + final CharSequence styled = getStyledSuggestionWord(suggestedWords, pos); mTexts.add(styled); } for (int pos = count; pos < countInStrip; pos++) { @@ -423,8 +451,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } } - private void layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { - final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP); + private void layoutPunctuationSuggestions(SuggestedWords suggestedWords, + ViewGroup stripView) { + final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP); for (int index = 0; index < countInStrip; index++) { if (index != 0) { // Add divider if this isn't the left most suggestion in suggestions strip. @@ -433,8 +462,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final TextView word = mWords.get(index); word.setEnabled(true); - word.setTextColor(mColorTypedWord); - final CharSequence text = suggestions.getWord(index); + word.setTextColor(mColorAutoCorrect); + final CharSequence text = suggestedWords.getWord(index); word.setText(text); word.setTextScaleX(1.0f); word.setCompoundDrawables(null, null, null, null); @@ -445,7 +474,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView, - int stripWidth) { + int stripWidth, CharSequence hintText) { final int width = stripWidth - mDividerWidth - mPadding * 2; final TextView wordView = mWordToSaveView; @@ -464,13 +493,85 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final TextView hintView = mHintToSaveView; hintView.setTextColor(mColorAutoCorrect); final int hintWidth = width - wordWidth; - final float hintScaleX = getTextScaleX(mHintToSaveText, hintWidth, hintView.getPaint()); - hintView.setText(mHintToSaveText); + final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint()); + hintView.setText(hintText); hintView.setTextScaleX(hintScaleX); stripView.addView(hintView); setLayoutWeight( hintView, 1.0f - mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT); } + + private static void setLayoutWeight(View v, float weight, int height) { + final ViewGroup.LayoutParams lp = v.getLayoutParams(); + if (lp instanceof LinearLayout.LayoutParams) { + final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp; + llp.weight = weight; + llp.width = 0; + llp.height = height; + } + } + + private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) { + paint.setTextScaleX(1.0f); + final int width = getTextWidth(text, paint); + if (width <= maxWidth) { + return 1.0f; + } + return maxWidth / (float)width; + } + + private static CharSequence getEllipsizedText(CharSequence text, int maxWidth, + TextPaint paint) { + if (text == null) return null; + paint.setTextScaleX(1.0f); + final int width = getTextWidth(text, paint); + if (width <= maxWidth) { + return text; + } + final float scaleX = maxWidth / (float)width; + if (scaleX >= MIN_TEXT_XSCALE) { + paint.setTextScaleX(scaleX); + return text; + } + + // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To + // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE). + final CharSequence ellipsized = TextUtils.ellipsize( + text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE); + paint.setTextScaleX(MIN_TEXT_XSCALE); + return ellipsized; + } + + private static int getTextWidth(CharSequence text, TextPaint paint) { + if (TextUtils.isEmpty(text)) return 0; + final Typeface savedTypeface = paint.getTypeface(); + paint.setTypeface(getTextTypeface(text)); + final int len = text.length(); + final float[] widths = new float[len]; + final int count = paint.getTextWidths(text, 0, len, widths); + int width = 0; + for (int i = 0; i < count; i++) { + width += Math.round(widths[i] + 0.5f); + } + paint.setTypeface(savedTypeface); + return width; + } + + private static Typeface getTextTypeface(CharSequence text) { + if (!(text instanceof SpannableString)) + return Typeface.DEFAULT; + + final SpannableString ss = (SpannableString)text; + final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class); + if (styles.length == 0) + return Typeface.DEFAULT; + + switch (styles[0].getStyle()) { + case Typeface.BOLD: return Typeface.DEFAULT_BOLD; + // TODO: BOLD_ITALIC, ITALIC case? + default: return Typeface.DEFAULT; + } + } } /** @@ -548,98 +649,17 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); } - public void setSuggestions(SuggestedWords suggestions) { - if (suggestions == null || suggestions.size() == 0) + public void setSuggestions(SuggestedWords suggestedWords) { + if (suggestedWords == null || suggestedWords.size() == 0) return; clear(); - mSuggestions = suggestions; - mParams.layout(mSuggestions, mSuggestionsStrip, this, getWidth()); - } - - private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) { - if (DBG && pos < suggestions.size()) { - final SuggestedWordInfo wordInfo = suggestions.getInfo(pos); - if (wordInfo != null) { - final CharSequence debugInfo = wordInfo.getDebugString(); - if (!TextUtils.isEmpty(debugInfo)) { - return debugInfo; - } - } - } - return null; - } - - private static void setLayoutWeight(View v, float weight, int height) { - final ViewGroup.LayoutParams lp = v.getLayoutParams(); - if (lp instanceof LinearLayout.LayoutParams) { - final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp; - llp.weight = weight; - llp.width = 0; - llp.height = height; - } - } - - private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) { - paint.setTextScaleX(1.0f); - final int width = getTextWidth(text, paint); - if (width <= maxWidth) { - return 1.0f; - } - return maxWidth / (float)width; + mSuggestedWords = suggestedWords; + mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); } - private static CharSequence getEllipsizedText(CharSequence text, int maxWidth, - TextPaint paint) { - if (text == null) return null; - paint.setTextScaleX(1.0f); - final int width = getTextWidth(text, paint); - if (width <= maxWidth) { - return text; - } - final float scaleX = maxWidth / (float)width; - if (scaleX >= MIN_TEXT_XSCALE) { - paint.setTextScaleX(scaleX); - return text; - } - - // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To get - // squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE). - final CharSequence ellipsized = TextUtils.ellipsize( - text, paint, maxWidth / MIN_TEXT_XSCALE, TextUtils.TruncateAt.MIDDLE); - paint.setTextScaleX(MIN_TEXT_XSCALE); - return ellipsized; - } - - private static int getTextWidth(CharSequence text, TextPaint paint) { - if (TextUtils.isEmpty(text)) return 0; - final Typeface savedTypeface = paint.getTypeface(); - paint.setTypeface(getTextTypeface(text)); - final int len = text.length(); - final float[] widths = new float[len]; - final int count = paint.getTextWidths(text, 0, len, widths); - int width = 0; - for (int i = 0; i < count; i++) { - width += Math.round(widths[i] + 0.5f); - } - paint.setTypeface(savedTypeface); - return width; - } - - private static Typeface getTextTypeface(CharSequence text) { - if (!(text instanceof SpannableString)) - return Typeface.DEFAULT; - - final SpannableString ss = (SpannableString)text; - final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class); - if (styles.length == 0) - return Typeface.DEFAULT; - - switch (styles[0].getStyle()) { - case Typeface.BOLD: return Typeface.DEFAULT_BOLD; - // TODO: BOLD_ITALIC, ITALIC case? - default: return Typeface.DEFAULT; - } + public int setMoreSuggestionsHeight(int remainingHeight) { + return mParams.setMoreSuggestionsHeight(remainingHeight); } public boolean isShowingAddToDictionaryHint() { @@ -647,9 +667,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, && mSuggestionsStrip.getChildAt(0) == mParams.mWordToSaveView; } - public void showAddToDictionaryHint(CharSequence word) { + public void showAddToDictionaryHint(CharSequence word, CharSequence hintText) { clear(); - mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth()); + mParams.layoutAddToDictionaryHint(word, mSuggestionsStrip, getWidth(), hintText); } public boolean dismissAddToDictionaryHint() { @@ -661,7 +681,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } public SuggestedWords getSuggestions() { - return mSuggestions; + return mSuggestedWords; } public void clear() { @@ -675,34 +695,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, mPreviewPopup.dismiss(); } - private void showPreview(View view, CharSequence word) { - if (TextUtils.isEmpty(word)) - return; - - final TextView previewText = mPreviewText; - previewText.setTextColor(mParams.mColorTypedWord); - previewText.setText(word); - previewText.measure( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - final int[] offsetInWindow = new int[2]; - view.getLocationInWindow(offsetInWindow); - final int posX = offsetInWindow[0]; - final int posY = offsetInWindow[1] - previewText.getMeasuredHeight(); - final PopupWindow previewPopup = mPreviewPopup; - if (previewPopup.isShowing()) { - previewPopup.update(posX, posY, previewPopup.getWidth(), previewPopup.getHeight()); - } else { - previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY); - } - previewText.setVisibility(VISIBLE); - mHandler.postHidePreview(); - } - private void addToDictionary(CharSequence word) { - if (mListener.addWordToDictionary(word.toString())) { - final CharSequence message = getContext().getString(R.string.added_word, word); - showPreview(mParams.mWordToSaveView, message); - } + mListener.addWordToDictionary(word.toString()); } private final KeyboardActionListener mMoreSuggestionsListener = @@ -710,7 +704,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, @Override public boolean onCustomRequest(int requestCode) { final int index = requestCode; - final CharSequence word = mSuggestions.getWord(index); + final CharSequence word = mSuggestedWords.getWord(index); mListener.pickSuggestionManually(index, word); dismissMoreSuggestions(); return true; @@ -755,9 +749,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; - builder.layout(mSuggestions, params.mSuggestionsCountInStrip, maxWidth, + builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth, (int)(maxWidth * params.mMinMoreSuggestionsWidth), - params.mMaxMoreSuggestionsRow); + params.getMaxMoreSuggestionsRow()); mMoreSuggestionsView.setKeyboard(builder.build()); container.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -832,8 +826,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, // Decided to be in the sliding input mode only when the touch point has been moved // upward. mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_SLIDING_MODE; - tracker.onShowMoreKeysPanel( - translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel); + tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel); } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { // Decided to be in the modal input mode mMoreSuggestionsMode = MORE_SUGGESTIONS_IN_MODAL_MODE; @@ -858,10 +851,10 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, if (!(tag instanceof Integer)) return; final int index = (Integer) tag; - if (index >= mSuggestions.size()) + if (index >= mSuggestedWords.size()) return; - final CharSequence word = mSuggestions.getWord(index); + final CharSequence word = mSuggestedWords.getWord(index); mListener.pickSuggestionManually(index, word); } diff --git a/native/Android.mk b/native/Android.mk index 24c0037c9..5053e7d64 100644 --- a/native/Android.mk +++ b/native/Android.mk @@ -1,64 +1 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/src - -LOCAL_CFLAGS += -Werror -Wall - -# To suppress compiler warnings for unused variables/functions used for debug features etc. -LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function - -LOCAL_SRC_FILES := \ - jni/com_android_inputmethod_keyboard_ProximityInfo.cpp \ - jni/com_android_inputmethod_latin_BinaryDictionary.cpp \ - jni/jni_common.cpp \ - src/bigram_dictionary.cpp \ - src/char_utils.cpp \ - src/correction.cpp \ - src/dictionary.cpp \ - src/proximity_info.cpp \ - src/unigram_dictionary.cpp - -#FLAG_DBG := true -#FLAG_DO_PROFILE := true - -TARGETING_UNBUNDLED_FROYO := true - -ifeq ($(TARGET_ARCH), x86) - TARGETING_UNBUNDLED_FROYO := false -endif - -ifeq ($(TARGET_ARCH),mips) - TARGETING_UNBUNDLED_FROYO := false -endif - -ifeq ($(FLAG_DBG), true) - TARGETING_UNBUNDLED_FROYO := false -endif - -ifeq ($(FLAG_DO_PROFILE), true) - TARGETING_UNBUNDLED_FROYO := false -endif - -ifeq ($(TARGETING_UNBUNDLED_FROYO), true) - LOCAL_NDK_VERSION := 4 - LOCAL_SDK_VERSION := 8 -endif - -LOCAL_MODULE := libjni_latinime - -LOCAL_MODULE_TAGS := optional - -ifeq ($(FLAG_DO_PROFILE), true) - $(warning Making profiling version of native library) - LOCAL_CFLAGS += -DFLAG_DO_PROFILE - LOCAL_SHARED_LIBRARIES := libcutils libutils -else # FLAG_DO_PROFILE -ifeq ($(FLAG_DBG), true) - $(warning Making debug version of native library) - LOCAL_CFLAGS += -DFLAG_DBG - LOCAL_SHARED_LIBRARIES := libcutils libutils -endif # FLAG_DBG -endif # FLAG_DO_PROFILE - -include $(BUILD_SHARED_LIBRARY) +include $(call all-subdir-makefiles) diff --git a/native/jni/Android.mk b/native/jni/Android.mk new file mode 100644 index 000000000..ffaede37d --- /dev/null +++ b/native/jni/Android.mk @@ -0,0 +1,92 @@ +# Copyright (C) 2011 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. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LATIN_IME_SRC_DIR := ../src + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR) + +LOCAL_CFLAGS += -Werror -Wall + +# To suppress compiler warnings for unused variables/functions used for debug features etc. +LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function + +LATIN_IME_JNI_SRC_FILES := \ + com_android_inputmethod_keyboard_ProximityInfo.cpp \ + com_android_inputmethod_latin_BinaryDictionary.cpp \ + jni_common.cpp + +LATIN_IME_CORE_SRC_FILES := \ + additional_proximity_chars.cpp \ + basechars.cpp \ + bigram_dictionary.cpp \ + char_utils.cpp \ + correction.cpp \ + dictionary.cpp \ + proximity_info.cpp \ + unigram_dictionary.cpp + +LOCAL_SRC_FILES := \ + $(LATIN_IME_JNI_SRC_FILES) \ + $(addprefix $(LATIN_IME_SRC_DIR)/,$(LATIN_IME_CORE_SRC_FILES)) + +#FLAG_DBG := true +#FLAG_DO_PROFILE := true + +TARGETING_UNBUNDLED_FROYO := true + +ifeq ($(TARGET_ARCH), x86) + TARGETING_UNBUNDLED_FROYO := false +endif + +ifeq ($(TARGET_ARCH), mips) + TARGETING_UNBUNDLED_FROYO := false +endif + +ifeq ($(FLAG_DBG), true) + TARGETING_UNBUNDLED_FROYO := false +endif + +ifeq ($(FLAG_DO_PROFILE), true) + TARGETING_UNBUNDLED_FROYO := false +endif + +ifeq ($(TARGETING_UNBUNDLED_FROYO), true) + LOCAL_NDK_VERSION := 4 + LOCAL_SDK_VERSION := 8 +endif + +LOCAL_MODULE := libjni_latinime + +LOCAL_MODULE_TAGS := optional + +# For STL +LOCAL_C_INCLUDES += external/stlport/stlport bionic +LOCAL_SHARED_LIBRARIES += libstlport + +ifeq ($(FLAG_DO_PROFILE), true) + $(warning Making profiling version of native library) + LOCAL_CFLAGS += -DFLAG_DO_PROFILE + LOCAL_SHARED_LIBRARIES += libcutils libutils +else # FLAG_DO_PROFILE +ifeq ($(FLAG_DBG), true) + $(warning Making debug version of native library) + LOCAL_CFLAGS += -DFLAG_DBG + LOCAL_SHARED_LIBRARIES += libcutils libutils +endif # FLAG_DBG +endif # FLAG_DO_PROFILE + +include $(BUILD_SHARED_LIBRARY) diff --git a/native/jni/Application.mk b/native/jni/Application.mk new file mode 100644 index 000000000..caf3b2622 --- /dev/null +++ b/native/jni/Application.mk @@ -0,0 +1 @@ +APP_STL := stlport_static diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp index 595ea2fdc..9eb437c06 100644 --- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp +++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp @@ -25,17 +25,20 @@ #include <assert.h> #include <errno.h> #include <stdio.h> +#include <string> namespace latinime { -static jint latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object, - jint maxProximityCharsSize, jint displayWidth, jint displayHeight, jint gridWidth, - jint gridHeight, jintArray proximityCharsArray, jint keyCount, - jintArray keyXCoordinateArray, jintArray keyYCoordinateArray, jintArray keyWidthArray, - jintArray keyHeightArray, jintArray keyCharCodeArray, +static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object, + jstring localejStr, jint maxProximityCharsSize, jint displayWidth, jint displayHeight, + jint gridWidth, jint gridHeight, jint mostCommonkeyWidth, jintArray proximityCharsArray, + jint keyCount, jintArray keyXCoordinateArray, jintArray keyYCoordinateArray, + jintArray keyWidthArray, jintArray keyHeightArray, jintArray keyCharCodeArray, jfloatArray sweetSpotCenterXArray, jfloatArray sweetSpotCenterYArray, jfloatArray sweetSpotRadiusArray) { - jint *proximityChars = env->GetIntArrayElements(proximityCharsArray, NULL); + const char *localeStrPtr = env->GetStringUTFChars(localejStr, 0); + const std::string localeStr(localeStrPtr); + jint *proximityChars = env->GetIntArrayElements(proximityCharsArray, 0); jint *keyXCoordinates = safeGetIntArrayElements(env, keyXCoordinateArray); jint *keyYCoordinates = safeGetIntArrayElements(env, keyYCoordinateArray); jint *keyWidths = safeGetIntArrayElements(env, keyWidthArray); @@ -44,8 +47,10 @@ static jint latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object, jfloat *sweetSpotCenterXs = safeGetFloatArrayElements(env, sweetSpotCenterXArray); jfloat *sweetSpotCenterYs = safeGetFloatArrayElements(env, sweetSpotCenterYArray); jfloat *sweetSpotRadii = safeGetFloatArrayElements(env, sweetSpotRadiusArray); - ProximityInfo *proximityInfo = new ProximityInfo(maxProximityCharsSize, displayWidth, - displayHeight, gridWidth, gridHeight, (const uint32_t*)proximityChars, + ProximityInfo *proximityInfo = new ProximityInfo( + localeStr, maxProximityCharsSize, displayWidth, + displayHeight, gridWidth, gridHeight, mostCommonkeyWidth, + (const int32_t*)proximityChars, keyCount, (const int32_t*)keyXCoordinates, (const int32_t*)keyYCoordinates, (const int32_t*)keyWidths, (const int32_t*)keyHeights, (const int32_t*)keyCharCodes, (const float*)sweetSpotCenterXs, (const float*)sweetSpotCenterYs, @@ -59,19 +64,20 @@ static jint latinime_Keyboard_setProximityInfo(JNIEnv *env, jobject object, safeReleaseIntArrayElements(env, keyYCoordinateArray, keyYCoordinates); safeReleaseIntArrayElements(env, keyXCoordinateArray, keyXCoordinates); env->ReleaseIntArrayElements(proximityCharsArray, proximityChars, 0); - return (jint)proximityInfo; + env->ReleaseStringUTFChars(localejStr, localeStrPtr); + return (jlong)proximityInfo; } -static void latinime_Keyboard_release(JNIEnv *env, jobject object, jint proximityInfo) { +static void latinime_Keyboard_release(JNIEnv *env, jobject object, jlong proximityInfo) { ProximityInfo *pi = (ProximityInfo*)proximityInfo; if (!pi) return; delete pi; } static JNINativeMethod sKeyboardMethods[] = { - {"setProximityInfoNative", "(IIIII[II[I[I[I[I[I[F[F[F)I", + {"setProximityInfoNative", "(Ljava/lang/String;IIIIII[II[I[I[I[I[I[F[F[F)J", (void*)latinime_Keyboard_setProximityInfo}, - {"releaseProximityInfoNative", "(I)V", (void*)latinime_Keyboard_release} + {"releaseProximityInfoNative", "(J)V", (void*)latinime_Keyboard_release} }; int register_ProximityInfo(JNIEnv *env) { diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 18c972444..f2878eea5 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "LatinIME: jni: BinaryDictionary" #include "binary_format.h" +#include "correction.h" #include "com_android_inputmethod_latin_BinaryDictionary.h" #include "dictionary.h" #include "jni.h" @@ -33,6 +34,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <unistd.h> #else // USE_MMAP_FOR_DICTIONARY #include <stdlib.h> #endif // USE_MMAP_FOR_DICTIONARY @@ -41,75 +43,75 @@ namespace latinime { void releaseDictBuf(void* dictBuf, const size_t length, int fd); -static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object, +static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, jstring sourceDir, jlong dictOffset, jlong dictSize, jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords, jint maxAlternatives) { PROF_OPEN; PROF_START(66); - const char *sourceDirChars = env->GetStringUTFChars(sourceDir, NULL); - if (sourceDirChars == NULL) { - LOGE("DICT: Can't get sourceDir string"); + const char *sourceDirChars = env->GetStringUTFChars(sourceDir, 0); + if (sourceDirChars == 0) { + AKLOGE("DICT: Can't get sourceDir string"); return 0; } int fd = 0; - void *dictBuf = NULL; + void *dictBuf = 0; int adjust = 0; #ifdef USE_MMAP_FOR_DICTIONARY /* mmap version */ fd = open(sourceDirChars, O_RDONLY); if (fd < 0) { - LOGE("DICT: Can't open sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno); + AKLOGE("DICT: Can't open sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno); return 0; } int pagesize = getpagesize(); adjust = dictOffset % pagesize; int adjDictOffset = dictOffset - adjust; int adjDictSize = dictSize + adjust; - dictBuf = mmap(NULL, sizeof(char) * adjDictSize, PROT_READ, MAP_PRIVATE, fd, adjDictOffset); + dictBuf = mmap(0, sizeof(char) * adjDictSize, PROT_READ, MAP_PRIVATE, fd, adjDictOffset); if (dictBuf == MAP_FAILED) { - LOGE("DICT: Can't mmap dictionary. errno=%d", errno); + AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno); return 0; } dictBuf = (void *)((char *)dictBuf + adjust); #else // USE_MMAP_FOR_DICTIONARY /* malloc version */ - FILE *file = NULL; + FILE *file = 0; file = fopen(sourceDirChars, "rb"); - if (file == NULL) { - LOGE("DICT: Can't fopen sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno); + if (file == 0) { + AKLOGE("DICT: Can't fopen sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno); return 0; } dictBuf = malloc(sizeof(char) * dictSize); if (!dictBuf) { - LOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno); + AKLOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno); return 0; } int ret = fseek(file, (long)dictOffset, SEEK_SET); if (ret != 0) { - LOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno); + AKLOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno); return 0; } ret = fread(dictBuf, sizeof(char) * dictSize, 1, file); if (ret != 1) { - LOGE("DICT: Failure in fread. ret=%d errno=%d", ret, errno); + AKLOGE("DICT: Failure in fread. ret=%d errno=%d", ret, errno); return 0; } ret = fclose(file); if (ret != 0) { - LOGE("DICT: Failure in fclose. ret=%d errno=%d", ret, errno); + AKLOGE("DICT: Failure in fclose. ret=%d errno=%d", ret, errno); return 0; } #endif // USE_MMAP_FOR_DICTIONARY env->ReleaseStringUTFChars(sourceDir, sourceDirChars); if (!dictBuf) { - LOGE("DICT: dictBuf is null"); + AKLOGE("DICT: dictBuf is null"); return 0; } - Dictionary *dictionary = NULL; + Dictionary *dictionary = 0; if (BinaryFormat::UNKNOWN_FORMAT == BinaryFormat::detectFormat((uint8_t*)dictBuf)) { - LOGE("DICT: dictionary format is unknown, bad magic number"); + AKLOGE("DICT: dictionary format is unknown, bad magic number"); #ifdef USE_MMAP_FOR_DICTIONARY releaseDictBuf(((char*)dictBuf) - adjust, adjDictSize, fd); #else // USE_MMAP_FOR_DICTIONARY @@ -121,23 +123,23 @@ static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object, } PROF_END(66); PROF_CLOSE; - return (jint)dictionary; + return (jlong)dictionary; } -static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jint dict, - jint proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, +static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, + jlong proximityInfo, jintArray xCoordinatesArray, jintArray yCoordinatesArray, jintArray inputArray, jint arraySize, jint flags, jcharArray outputArray, jintArray frequencyArray) { Dictionary *dictionary = (Dictionary*)dict; if (!dictionary) return 0; ProximityInfo *pInfo = (ProximityInfo*)proximityInfo; - int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, NULL); - int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, NULL); + int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0); + int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0); - int *frequencies = env->GetIntArrayElements(frequencyArray, NULL); - int *inputCodes = env->GetIntArrayElements(inputArray, NULL); - jchar *outputChars = env->GetCharArrayElements(outputArray, NULL); + int *frequencies = env->GetIntArrayElements(frequencyArray, 0); + int *inputCodes = env->GetIntArrayElements(inputArray, 0); + jchar *outputChars = env->GetCharArrayElements(outputArray, 0); int count = dictionary->getSuggestions(pInfo, xCoordinates, yCoordinates, inputCodes, arraySize, flags, (unsigned short*) outputChars, frequencies); @@ -151,17 +153,17 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, return count; } -static int latinime_BinaryDictionary_getBigrams(JNIEnv *env, jobject object, jint dict, +static int latinime_BinaryDictionary_getBigrams(JNIEnv *env, jobject object, jlong dict, jcharArray prevWordArray, jint prevWordLength, jintArray inputArray, jint inputArraySize, jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxBigrams, jint maxAlternatives) { Dictionary *dictionary = (Dictionary*)dict; if (!dictionary) return 0; - jchar *prevWord = env->GetCharArrayElements(prevWordArray, NULL); - int *inputCodes = env->GetIntArrayElements(inputArray, NULL); - jchar *outputChars = env->GetCharArrayElements(outputArray, NULL); - int *frequencies = env->GetIntArrayElements(frequencyArray, NULL); + jchar *prevWord = env->GetCharArrayElements(prevWordArray, 0); + int *inputCodes = env->GetIntArrayElements(inputArray, 0); + jchar *outputChars = env->GetCharArrayElements(outputArray, 0); + int *frequencies = env->GetIntArrayElements(frequencyArray, 0); int count = dictionary->getBigrams((unsigned short*) prevWord, prevWordLength, inputCodes, inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams, @@ -175,19 +177,42 @@ static int latinime_BinaryDictionary_getBigrams(JNIEnv *env, jobject object, jin return count; } -static jboolean latinime_BinaryDictionary_isValidWord(JNIEnv *env, jobject object, jint dict, +static jboolean latinime_BinaryDictionary_isValidWord(JNIEnv *env, jobject object, jlong dict, jcharArray wordArray, jint wordLength) { Dictionary *dictionary = (Dictionary*)dict; if (!dictionary) return (jboolean) false; - jchar *word = env->GetCharArrayElements(wordArray, NULL); + jchar *word = env->GetCharArrayElements(wordArray, 0); jboolean result = dictionary->isValidWord((unsigned short*) word, wordLength); env->ReleaseCharArrayElements(wordArray, word, JNI_ABORT); return result; } -static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jint dict) { +static jdouble latinime_BinaryDictionary_calcNormalizedScore(JNIEnv *env, jobject object, + jcharArray before, jint beforeLength, jcharArray after, jint afterLength, jint score) { + jchar *beforeChars = env->GetCharArrayElements(before, 0); + jchar *afterChars = env->GetCharArrayElements(after, 0); + jdouble result = Correction::RankingAlgorithm::calcNormalizedScore( + (unsigned short*)beforeChars, beforeLength, (unsigned short*)afterChars, afterLength, + score); + env->ReleaseCharArrayElements(before, beforeChars, JNI_ABORT); + env->ReleaseCharArrayElements(after, afterChars, JNI_ABORT); + return result; +} + +static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object, + jcharArray before, jint beforeLength, jcharArray after, jint afterLength) { + jchar *beforeChars = env->GetCharArrayElements(before, 0); + jchar *afterChars = env->GetCharArrayElements(after, 0); + jint result = Correction::RankingAlgorithm::editDistance( + (unsigned short*)beforeChars, beforeLength, (unsigned short*)afterChars, afterLength); + env->ReleaseCharArrayElements(before, beforeChars, JNI_ABORT); + env->ReleaseCharArrayElements(after, afterChars, JNI_ABORT); + return result; +} + +static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jlong dict) { Dictionary *dictionary = (Dictionary*)dict; if (!dictionary) return; void *dictBuf = dictionary->getDict(); @@ -205,11 +230,11 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) { #ifdef USE_MMAP_FOR_DICTIONARY int ret = munmap(dictBuf, length); if (ret != 0) { - LOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno); + AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno); } ret = close(fd); if (ret != 0) { - LOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno); + AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno); } #else // USE_MMAP_FOR_DICTIONARY free(dictBuf); @@ -217,11 +242,14 @@ void releaseDictBuf(void* dictBuf, const size_t length, int fd) { } static JNINativeMethod sMethods[] = { - {"openNative", "(Ljava/lang/String;JJIIIII)I", (void*)latinime_BinaryDictionary_open}, - {"closeNative", "(I)V", (void*)latinime_BinaryDictionary_close}, - {"getSuggestionsNative", "(II[I[I[III[C[I)I", (void*)latinime_BinaryDictionary_getSuggestions}, - {"isValidWordNative", "(I[CI)Z", (void*)latinime_BinaryDictionary_isValidWord}, - {"getBigramsNative", "(I[CI[II[C[IIII)I", (void*)latinime_BinaryDictionary_getBigrams} + {"openNative", "(Ljava/lang/String;JJIIIII)J", (void*)latinime_BinaryDictionary_open}, + {"closeNative", "(J)V", (void*)latinime_BinaryDictionary_close}, + {"getSuggestionsNative", "(JJ[I[I[III[C[I)I", (void*)latinime_BinaryDictionary_getSuggestions}, + {"isValidWordNative", "(J[CI)Z", (void*)latinime_BinaryDictionary_isValidWord}, + {"getBigramsNative", "(J[CI[II[C[IIII)I", (void*)latinime_BinaryDictionary_getBigrams}, + {"calcNormalizedScoreNative", "([CI[CII)D", + (void*)latinime_BinaryDictionary_calcNormalizedScore}, + {"editDistanceNative", "([CI[CI)I", (void*)latinime_BinaryDictionary_editDistance} }; int register_BinaryDictionary(JNIEnv *env) { diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp index 8643f723f..85d26836a 100644 --- a/native/jni/jni_common.cpp +++ b/native/jni/jni_common.cpp @@ -32,22 +32,22 @@ using namespace latinime; * Returns the JNI version on success, -1 on failure. */ jint JNI_OnLoad(JavaVM* vm, void* reserved) { - JNIEnv* env = NULL; + JNIEnv* env = 0; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - LOGE("ERROR: GetEnv failed"); + AKLOGE("ERROR: GetEnv failed"); goto bail; } - assert(env != NULL); + assert(env != 0); if (!register_BinaryDictionary(env)) { - LOGE("ERROR: BinaryDictionary native registration failed"); + AKLOGE("ERROR: BinaryDictionary native registration failed"); goto bail; } if (!register_ProximityInfo(env)) { - LOGE("ERROR: ProximityInfo native registration failed"); + AKLOGE("ERROR: ProximityInfo native registration failed"); goto bail; } @@ -63,12 +63,12 @@ namespace latinime { int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* methods, int numMethods) { jclass clazz = env->FindClass(className); - if (clazz == NULL) { - LOGE("Native registration unable to find class '%s'", className); + if (clazz == 0) { + AKLOGE("Native registration unable to find class '%s'", className); return JNI_FALSE; } if (env->RegisterNatives(clazz, methods, numMethods) < 0) { - LOGE("RegisterNatives failed for '%s'", className); + AKLOGE("RegisterNatives failed for '%s'", className); env->DeleteLocalRef(clazz); return JNI_FALSE; } diff --git a/native/jni/jni_common.h b/native/jni/jni_common.h index 9548e1b3f..6741443ac 100644 --- a/native/jni/jni_common.h +++ b/native/jni/jni_common.h @@ -29,17 +29,17 @@ int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *m inline jint *safeGetIntArrayElements(JNIEnv *env, jintArray jArray) { if (jArray) { - return env->GetIntArrayElements(jArray, NULL); + return env->GetIntArrayElements(jArray, 0); } else { - return NULL; + return 0; } } inline jfloat *safeGetFloatArrayElements(JNIEnv *env, jfloatArray jArray) { if (jArray) { - return env->GetFloatArrayElements(jArray, NULL); + return env->GetFloatArrayElements(jArray, 0); } else { - return NULL; + return 0; } } diff --git a/native/src/additional_proximity_chars.cpp b/native/src/additional_proximity_chars.cpp new file mode 100644 index 000000000..224f020f2 --- /dev/null +++ b/native/src/additional_proximity_chars.cpp @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#include "additional_proximity_chars.h" + +namespace latinime { +const std::string AdditionalProximityChars::LOCALE_EN_US("en"); + +const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = { + 'e', 'i', 'o', 'u' +}; + +const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_E[EN_US_ADDITIONAL_E_SIZE] = { + 'a', 'i', 'o', 'u' +}; + +const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_I[EN_US_ADDITIONAL_I_SIZE] = { + 'a', 'e', 'o', 'u' +}; + +const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_O[EN_US_ADDITIONAL_O_SIZE] = { + 'a', 'e', 'i', 'u' +}; + +const int32_t AdditionalProximityChars::EN_US_ADDITIONAL_U[EN_US_ADDITIONAL_U_SIZE] = { + 'a', 'e', 'i', 'o' +}; +} diff --git a/native/src/additional_proximity_chars.h b/native/src/additional_proximity_chars.h new file mode 100644 index 000000000..e0ecc0e1d --- /dev/null +++ b/native/src/additional_proximity_chars.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef LATINIME_ADDITIONAL_PROXIMITY_CHARS_H +#define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H + +#include <stdint.h> +#include <string> + +#include "defines.h" + +namespace latinime { + +class AdditionalProximityChars { + private: + static const std::string LOCALE_EN_US; + static const int EN_US_ADDITIONAL_A_SIZE = 4; + static const int32_t EN_US_ADDITIONAL_A[]; + static const int EN_US_ADDITIONAL_E_SIZE = 4; + static const int32_t EN_US_ADDITIONAL_E[]; + static const int EN_US_ADDITIONAL_I_SIZE = 4; + static const int32_t EN_US_ADDITIONAL_I[]; + static const int EN_US_ADDITIONAL_O_SIZE = 4; + static const int32_t EN_US_ADDITIONAL_O[]; + static const int EN_US_ADDITIONAL_U_SIZE = 4; + static const int32_t EN_US_ADDITIONAL_U[]; + + static bool isEnLocale(const std::string *locale_str) { + return locale_str && locale_str->size() >= LOCALE_EN_US.size() + && LOCALE_EN_US.compare(0, LOCALE_EN_US.size(), *locale_str); + } + + public: + static int getAdditionalCharsSize(const std::string* locale_str, const int32_t c) { + if (!isEnLocale(locale_str)) { + return 0; + } + switch(c) { + case 'a': + return EN_US_ADDITIONAL_A_SIZE; + case 'e': + return EN_US_ADDITIONAL_E_SIZE; + case 'i': + return EN_US_ADDITIONAL_I_SIZE; + case 'o': + return EN_US_ADDITIONAL_O_SIZE; + case 'u': + return EN_US_ADDITIONAL_U_SIZE; + default: + return 0; + } + } + + static const int32_t* getAdditionalChars(const std::string *locale_str, const int32_t c) { + if (!isEnLocale(locale_str)) { + return 0; + } + switch(c) { + case 'a': + return EN_US_ADDITIONAL_A; + case 'e': + return EN_US_ADDITIONAL_E; + case 'i': + return EN_US_ADDITIONAL_I; + case 'o': + return EN_US_ADDITIONAL_O; + case 'u': + return EN_US_ADDITIONAL_U; + default: + return 0; + } + } + + static bool hasAdditionalChars(const std::string *locale_str, const int32_t c) { + return getAdditionalCharsSize(locale_str, c) > 0; + } +}; + +} + +#endif // LATINIME_ADDITIONAL_PROXIMITY_CHARS_H diff --git a/native/src/basechars.h b/native/src/basechars.cpp index 3843e11c5..31f1e18a8 100644 --- a/native/src/basechars.h +++ b/native/src/basechars.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2011 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. @@ -14,8 +14,9 @@ * limitations under the License. */ -#ifndef LATINIME_BASECHARS_H -#define LATINIME_BASECHARS_H +#include "char_utils.h" + +namespace latinime { /** * Table mapping most combined Latin, Greek, and Cyrillic characters @@ -23,7 +24,7 @@ * if c is not a combined character, or the base character if it * is combined. */ -static unsigned short BASE_CHARS[] = { +const unsigned short BASE_CHARS[BASE_CHARS_SIZE] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, @@ -189,4 +190,5 @@ static unsigned short BASE_CHARS[] = { // generated with: // cat UnicodeData.txt | perl -e 'while (<>) { @foo = split(/;/); $foo[5] =~ s/<.*> //; $base[hex($foo[0])] = hex($foo[5]);} for ($i = 0; $i < 0x500; $i += 8) { for ($j = $i; $j < $i + 8; $j++) { printf("0x%04x, ", $base[$j] ? $base[$j] : $j)}; print "\n"; }' -#endif // LATINIME_BASECHARS_H + +} // namespace latinime diff --git a/native/src/bigram_dictionary.cpp b/native/src/bigram_dictionary.cpp index c340c6c1a..84048d77d 100644 --- a/native/src/bigram_dictionary.cpp +++ b/native/src/bigram_dictionary.cpp @@ -28,12 +28,12 @@ namespace latinime { BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength, int maxAlternatives, const bool isLatestDictVersion, const bool hasBigram, Dictionary *parentDictionary) - : DICT(dict + NEW_DICTIONARY_HEADER_SIZE), MAX_WORD_LENGTH(maxWordLength), + : DICT(dict), MAX_WORD_LENGTH(maxWordLength), MAX_ALTERNATIVES(maxAlternatives), IS_LATEST_DICT_VERSION(isLatestDictVersion), HAS_BIGRAM(hasBigram), mParentDictionary(parentDictionary) { if (DEBUG_DICT) { - LOGI("BigramDictionary - constructor"); - LOGI("Has Bigram : %d", hasBigram); + AKLOGI("BigramDictionary - constructor"); + AKLOGI("Has Bigram : %d", hasBigram); } } @@ -46,7 +46,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ #ifdef FLAG_DBG char s[length + 1]; for (int i = 0; i <= length; i++) s[i] = word[i]; - LOGI("Bigram: Found word = %s, freq = %d :", s, frequency); + AKLOGI("Bigram: Found word = %s, freq = %d :", s, frequency); #endif } @@ -60,7 +60,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ insertAt++; } if (DEBUG_DICT) { - LOGI("Bigram: InsertAt -> %d maxBigrams: %d", insertAt, mMaxBigrams); + AKLOGI("Bigram: InsertAt -> %d maxBigrams: %d", insertAt, mMaxBigrams); } if (insertAt < mMaxBigrams) { memmove((char*) mBigramFreq + (insertAt + 1) * sizeof(mBigramFreq[0]), @@ -76,7 +76,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ } *dest = 0; // NULL terminate if (DEBUG_DICT) { - LOGI("Bigram: Added word at %d", insertAt); + AKLOGI("Bigram: Added word at %d", insertAt); } return true; } @@ -134,7 +134,8 @@ int BigramDictionary::getBigrams(unsigned short *prevWord, int prevWordLength, i const int length = BinaryFormat::getWordAtAddress(root, bigramPos, MAX_WORD_LENGTH, bigramBuffer); - if (checkFirstCharacter(bigramBuffer)) { + // codesSize == 0 means we are trying to find bigram predictions. + if (codesSize < 1 || checkFirstCharacter(bigramBuffer)) { const int frequency = UnigramDictionary::MASK_ATTRIBUTE_FREQUENCY & bigramFlags; addWordBigram(bigramBuffer, length, frequency); } diff --git a/native/src/bigram_dictionary.h b/native/src/bigram_dictionary.h index c07458a38..585a1866a 100644 --- a/native/src/bigram_dictionary.h +++ b/native/src/bigram_dictionary.h @@ -21,14 +21,14 @@ namespace latinime { class Dictionary; class BigramDictionary { -public: + public: BigramDictionary(const unsigned char *dict, int maxWordLength, int maxAlternatives, const bool isLatestDictVersion, const bool hasBigram, Dictionary *parentDictionary); int getBigrams(unsigned short *word, int length, int *codes, int codesSize, unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams, int maxAlternatives); ~BigramDictionary(); -private: + private: bool addWordBigram(unsigned short *word, int length, int frequency); int getBigramAddress(int *pos, bool advance); int getBigramFreq(int *pos); diff --git a/native/src/binary_format.h b/native/src/binary_format.h index 6f65088db..ab033ad90 100644 --- a/native/src/binary_format.h +++ b/native/src/binary_format.h @@ -17,22 +17,31 @@ #ifndef LATINIME_BINARY_FORMAT_H #define LATINIME_BINARY_FORMAT_H +#include <limits> #include "unigram_dictionary.h" namespace latinime { class BinaryFormat { -private: + private: const static int32_t MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20; const static int32_t CHARACTER_ARRAY_TERMINATOR = 0x1F; const static int MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE = 2; -public: + public: const static int UNKNOWN_FORMAT = -1; - const static int FORMAT_VERSION_1 = 1; - const static uint16_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B1; + // Originally, format version 1 had a 16-bit magic number, then the version number `01' + // then options that must be 0. Hence the first 32-bits of the format are always as follow + // and it's okay to consider them a magic number as a whole. + const static uint32_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B10100; + const static unsigned int FORMAT_VERSION_1_HEADER_SIZE = 5; + // The versions of Latin IME that only handle format version 1 only test for the magic + // number, so we had to change it so that version 2 files would be rejected by older + // implementations. On this occasion, we made the magic number 32 bits long. + const static uint32_t FORMAT_VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; static int detectFormat(const uint8_t* const dict); + static unsigned int getHeaderSize(const uint8_t* const dict); static int getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos); static uint8_t getFlagsAndForwardPointer(const uint8_t* const dict, int* pos); static int32_t getCharCodeAndForwardPointer(const uint8_t* const dict, int* pos); @@ -55,13 +64,43 @@ public: }; inline int BinaryFormat::detectFormat(const uint8_t* const dict) { - const uint16_t magicNumber = (dict[0] << 8) + dict[1]; // big endian - if (FORMAT_VERSION_1_MAGIC_NUMBER == magicNumber) return FORMAT_VERSION_1; - return UNKNOWN_FORMAT; + // The magic number is stored big-endian. + const uint32_t magicNumber = (dict[0] << 24) + (dict[1] << 16) + (dict[2] << 8) + dict[3]; + switch (magicNumber) { + case FORMAT_VERSION_1_MAGIC_NUMBER: + // Format 1 header is exactly 5 bytes long and looks like: + // Magic number (2 bytes) 0x78 0xB1 + // Version number (1 byte) 0x01 + // Options (2 bytes) must be 0x00 0x00 + return 1; + case FORMAT_VERSION_2_MAGIC_NUMBER: + // Format 2 header is as follows: + // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE + // Version number (2 bytes) 0x00 0x02 + // Options (2 bytes) must be 0x00 0x00 + // Header size (4 bytes) : integer, big endian + return (dict[4] << 8) + dict[5]; + default: + return UNKNOWN_FORMAT; + } +} + +inline unsigned int BinaryFormat::getHeaderSize(const uint8_t* const dict) { + switch (detectFormat(dict)) { + case 1: + return FORMAT_VERSION_1_HEADER_SIZE; + case 2: + // See the format of the header in the comment in detectFormat() above + return (dict[8] << 24) + (dict[9] << 16) + (dict[10] << 8) + dict[11]; + default: + return std::numeric_limits<unsigned int>::max(); + } } inline int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t* const dict, int* pos) { - return dict[(*pos)++]; + const int msb = dict[(*pos)++]; + if (msb < 0x80) return msb; + return ((msb & 0x7F) << 8) | dict[(*pos)++]; } inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t* const dict, int* pos) { @@ -145,15 +184,15 @@ inline int BinaryFormat::skipFrequency(const uint8_t flags, const int pos) { inline int BinaryFormat::skipAllAttributes(const uint8_t* const dict, const uint8_t flags, const int pos) { - // This function skips all attributes. The format makes provision for future extension - // with other attributes (notably shortcuts) but for the time being, bigrams are the - // only attributes that may be found in a character group, so we only look at bigrams - // in this version. + // This function skips all attributes: shortcuts and bigrams. + int newPos = pos; + if (UnigramDictionary::FLAG_HAS_SHORTCUT_TARGETS & flags) { + newPos = skipAttributes(dict, newPos); + } if (UnigramDictionary::FLAG_HAS_BIGRAMS & flags) { - return skipAttributes(dict, pos); - } else { - return pos; + newPos = skipAttributes(dict, newPos); } + return newPos; } inline int BinaryFormat::skipChildrenPosAndAttributes(const uint8_t* const dict, diff --git a/native/src/char_utils.h b/native/src/char_utils.h index a69a35e7a..607dc5195 100644 --- a/native/src/char_utils.h +++ b/native/src/char_utils.h @@ -19,8 +19,47 @@ namespace latinime { +inline static int isAsciiUpper(unsigned short c) { + return c >= 'A' && c <= 'Z'; +} + +inline static unsigned short toAsciiLower(unsigned short c) { + return c - 'A' + 'a'; +} + +inline static int isAscii(unsigned short c) { + return c <= 127; +} + unsigned short latin_tolower(unsigned short c); +/** + * Table mapping most combined Latin, Greek, and Cyrillic characters + * to their base characters. If c is in range, BASE_CHARS[c] == c + * if c is not a combined character, or the base character if it + * is combined. + */ + +static const int BASE_CHARS_SIZE = 0x0500; +extern const unsigned short BASE_CHARS[BASE_CHARS_SIZE]; + +inline static unsigned short toBaseChar(unsigned short c) { + if (c < BASE_CHARS_SIZE) { + return BASE_CHARS[c]; + } + return c; +} + +inline static unsigned short toBaseLowerCase(unsigned short c) { + c = toBaseChar(c); + if (isAsciiUpper(c)) { + return toAsciiLower(c); + } else if (isAscii(c)) { + return c; + } + return latin_tolower(c); +} + } // namespace latinime #endif // LATINIME_CHAR_UTILS_H diff --git a/native/src/correction.cpp b/native/src/correction.cpp index 27dc40745..087219ed4 100644 --- a/native/src/correction.cpp +++ b/native/src/correction.cpp @@ -16,12 +16,15 @@ #include <assert.h> #include <ctype.h> +#include <math.h> #include <stdio.h> #include <string.h> #define LOG_TAG "LatinIME: correction.cpp" +#include "char_utils.h" #include "correction.h" +#include "defines.h" #include "dictionary.h" #include "proximity_info.h" @@ -31,81 +34,60 @@ namespace latinime { // edit distance funcitons // ///////////////////////////// -#if 0 /* no longer used */ -inline static int editDistance( - int* editDistanceTable, const unsigned short* input, - const int inputLength, const unsigned short* output, const int outputLength) { - // dp[li][lo] dp[a][b] = dp[ a * lo + b] - int* dp = editDistanceTable; - const int li = inputLength + 1; - const int lo = outputLength + 1; - for (int i = 0; i < li; ++i) { - dp[lo * i] = i; - } - for (int i = 0; i < lo; ++i) { - dp[i] = i; - } - - for (int i = 0; i < li - 1; ++i) { - for (int j = 0; j < lo - 1; ++j) { - const uint32_t ci = Dictionary::toBaseLowerCase(input[i]); - const uint32_t co = Dictionary::toBaseLowerCase(output[j]); - const uint16_t cost = (ci == co) ? 0 : 1; - dp[(i + 1) * lo + (j + 1)] = min(dp[i * lo + (j + 1)] + 1, - min(dp[(i + 1) * lo + j] + 1, dp[i * lo + j] + cost)); - if (i > 0 && j > 0 && ci == Dictionary::toBaseLowerCase(output[j - 1]) - && co == Dictionary::toBaseLowerCase(input[i - 1])) { - dp[(i + 1) * lo + (j + 1)] = min( - dp[(i + 1) * lo + (j + 1)], dp[(i - 1) * lo + (j - 1)] + cost); - } - } +inline static void initEditDistance(int *editDistanceTable) { + for (int i = 0; i <= MAX_WORD_LENGTH_INTERNAL; ++i) { + editDistanceTable[i] = i; } +} - if (DEBUG_EDIT_DISTANCE) { - LOGI("IN = %d, OUT = %d", inputLength, outputLength); - for (int i = 0; i < li; ++i) { - for (int j = 0; j < lo; ++j) { - LOGI("EDIT[%d][%d], %d", i, j, dp[i * lo + j]); +inline static void dumpEditDistance10ForDebug(int *editDistanceTable, + const int editDistanceTableWidth, const int outputLength) { + if (DEBUG_DICT) { + AKLOGI("EditDistanceTable"); + for (int i = 0; i <= 10; ++i) { + int c[11]; + for (int j = 0; j <= 10; ++j) { + if (j < editDistanceTableWidth + 1 && i < outputLength + 1) { + c[j] = (editDistanceTable + i * (editDistanceTableWidth + 1))[j]; + } else { + c[j] = -1; + } } + AKLOGI("[ %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d ]", + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10]); } } - return dp[li * lo - 1]; -} -#endif - -inline static void initEditDistance(int *editDistanceTable) { - for (int i = 0; i <= MAX_WORD_LENGTH_INTERNAL; ++i) { - editDistanceTable[i] = i; - } } inline static void calcEditDistanceOneStep(int *editDistanceTable, const unsigned short *input, const int inputLength, const unsigned short *output, const int outputLength) { + // TODO: Make sure that editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] is not touched. // Let dp[i][j] be editDistanceTable[i * (inputLength + 1) + j]. // Assuming that dp[0][0] ... dp[outputLength - 1][inputLength] are already calculated, // and calculate dp[ouputLength][0] ... dp[outputLength][inputLength]. int *const current = editDistanceTable + outputLength * (inputLength + 1); const int *const prev = editDistanceTable + (outputLength - 1) * (inputLength + 1); const int *const prevprev = - outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputLength + 1) : NULL; + outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputLength + 1) : 0; current[0] = outputLength; - const uint32_t co = Dictionary::toBaseLowerCase(output[outputLength - 1]); - const uint32_t prevCO = - outputLength >= 2 ? Dictionary::toBaseLowerCase(output[outputLength - 2]) : 0; + const uint32_t co = toBaseLowerCase(output[outputLength - 1]); + const uint32_t prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; for (int i = 1; i <= inputLength; ++i) { - const uint32_t ci = Dictionary::toBaseLowerCase(input[i - 1]); + const uint32_t ci = toBaseLowerCase(input[i - 1]); const uint16_t cost = (ci == co) ? 0 : 1; current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost)); - if (i >= 2 && prevprev && ci == prevCO - && co == Dictionary::toBaseLowerCase(input[i - 2])) { + if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) { current[i] = min(current[i], prevprev[i - 2] + 1); } } } -inline static int getCurrentEditDistance( - int *editDistanceTable, const int inputLength, const int outputLength) { - return editDistanceTable[(inputLength + 1) * (outputLength + 1) - 1]; +inline static int getCurrentEditDistance(int *editDistanceTable, const int editDistanceTableWidth, + const int outputLength, const int inputLength) { + if (DEBUG_EDIT_DISTANCE) { + AKLOGI("getCurrentEditDistance %d, %d", inputLength, outputLength); + } + return editDistanceTable[(editDistanceTableWidth + 1) * (outputLength) + inputLength]; } ////////////////////// @@ -133,6 +115,9 @@ void Correction::initCorrection(const ProximityInfo *pi, const int inputLength, mInputLength = inputLength; mMaxDepth = maxDepth; mMaxEditDistance = mInputLength < 5 ? 2 : mInputLength / 2; + // TODO: This is not supposed to be required. Check what's going wrong with + // editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] + initEditDistance(mEditDistanceTable); } void Correction::initCorrectionState( @@ -146,7 +131,7 @@ void Correction::initCorrectionState( void Correction::setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos, const int spaceProximityPos, const int missingSpacePos, - const bool useFullEditDistance) { + const bool useFullEditDistance, const bool doAutoCompletion, const int maxErrors) { // TODO: remove mTransposedPos = transposedPos; mExcessivePos = excessivePos; @@ -159,6 +144,8 @@ void Correction::setCorrectionParams(const int skipPos, const int excessivePos, mSpaceProximityPos = spaceProximityPos; mMissingSpacePos = missingSpacePos; mUseFullEditDistance = useFullEditDistance; + mDoAutoCompletion = doAutoCompletion; + mMaxErrors = maxErrors; } void Correction::checkState() { @@ -172,23 +159,34 @@ void Correction::checkState() { } } -int Correction::getFreqForSplitTwoWords(const int firstFreq, const int secondFreq, - const unsigned short *word) { - return Correction::RankingAlgorithm::calcFreqForSplitTwoWords( - firstFreq, secondFreq, this, word); +int Correction::getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, + const int wordCount, const bool isSpaceProximity, const unsigned short *word) { + return Correction::RankingAlgorithm::calcFreqForSplitMultipleWords(freqArray, wordLengthArray, + wordCount, this, isSpaceProximity, word); } int Correction::getFinalFreq(const int freq, unsigned short **word, int *wordLength) { + return getFinalFreqInternal(freq, word, wordLength, mInputLength); +} + +int Correction::getFinalFreqForSubQueue(const int freq, unsigned short **word, int *wordLength, + const int inputLength) { + return getFinalFreqInternal(freq, word, wordLength, inputLength); +} + +int Correction::getFinalFreqInternal(const int freq, unsigned short **word, int *wordLength, + const int inputLength) { const int outputIndex = mTerminalOutputIndex; const int inputIndex = mTerminalInputIndex; *wordLength = outputIndex + 1; - if (mProximityInfo->sameAsTyped(mWord, outputIndex + 1) || outputIndex < MIN_SUGGEST_DEPTH) { - return -1; + if (outputIndex < MIN_SUGGEST_DEPTH) { + return NOT_A_FREQUENCY; } *word = mWord; - return Correction::RankingAlgorithm::calculateFinalFreq( - inputIndex, outputIndex, freq, mEditDistanceTable, this); + int finalFreq = Correction::RankingAlgorithm::calculateFinalFreq( + inputIndex, outputIndex, freq, mEditDistanceTable, this, inputLength); + return finalFreq; } bool Correction::initProcessState(const int outputIndex) { @@ -213,6 +211,7 @@ bool Correction::initProcessState(const int outputIndex) { mMatching = false; mProximityMatching = false; + mAdditionalProximityMatching = false; mTransposing = false; mExceeding = false; mSkipping = false; @@ -229,20 +228,10 @@ int Correction::goDownTree( } // TODO: remove -int Correction::getOutputIndex() { - return mOutputIndex; -} - -// TODO: remove int Correction::getInputIndex() { return mInputIndex; } -// TODO: remove -bool Correction::needsToTraverseAllNodes() { - return mNeedsToTraverseAllNodes; -} - void Correction::incrementInputIndex() { ++mInputIndex; } @@ -269,6 +258,7 @@ void Correction::incrementOutputIndex() { mCorrectionStates[mOutputIndex].mMatching = mMatching; mCorrectionStates[mOutputIndex].mProximityMatching = mProximityMatching; + mCorrectionStates[mOutputIndex].mAdditionalProximityMatching = mAdditionalProximityMatching; mCorrectionStates[mOutputIndex].mTransposing = mTransposing; mCorrectionStates[mOutputIndex].mExceeding = mExceeding; mCorrectionStates[mOutputIndex].mSkipping = mSkipping; @@ -280,7 +270,9 @@ void Correction::startToTraverseAllNodes() { bool Correction::needsToPrune() const { // TODO: use edit distance here - return mOutputIndex - 1 >= mMaxDepth || mProximityCount > mMaxEditDistance; + return mOutputIndex - 1 >= mMaxDepth || mProximityCount > mMaxEditDistance + // Allow one char longer word for missing character + || (!mDoAutoCompletion && (mOutputIndex > mInputLength)); } void Correction::addCharToCurrentWord(const int32_t c) { @@ -290,13 +282,12 @@ void Correction::addCharToCurrentWord(const int32_t c) { mWord, mOutputIndex + 1); } -// TODO: inline? Correction::CorrectionType Correction::processSkipChar( const int32_t c, const bool isTerminal, const bool inputIndexIncremented) { addCharToCurrentWord(c); - if (needsToTraverseAllNodes() && isTerminal) { - mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); - mTerminalOutputIndex = mOutputIndex; + mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); + mTerminalOutputIndex = mOutputIndex; + if (mNeedsToTraverseAllNodes && isTerminal) { incrementOutputIndex(); return TRAVERSE_ALL_ON_TERMINAL; } else { @@ -305,19 +296,36 @@ Correction::CorrectionType Correction::processSkipChar( } } +Correction::CorrectionType Correction::processUnrelatedCorrectionType() { + // Needs to set mTerminalInputIndex and mTerminalOutputIndex before returning any CorrectionType + mTerminalInputIndex = mInputIndex; + mTerminalOutputIndex = mOutputIndex; + return UNRELATED; +} + inline bool isEquivalentChar(ProximityInfo::ProximityType type) { return type == ProximityInfo::EQUIVALENT_CHAR; } +inline bool isProximityCharOrEquivalentChar(ProximityInfo::ProximityType type) { + return type == ProximityInfo::EQUIVALENT_CHAR + || type == ProximityInfo::NEAR_PROXIMITY_CHAR; +} + Correction::CorrectionType Correction::processCharAndCalcState( const int32_t c, const bool isTerminal) { const int correctionCount = (mSkippedCount + mExcessiveCount + mTransposedCount); + if (correctionCount > mMaxErrors) { + return processUnrelatedCorrectionType(); + } + // TODO: Change the limit if we'll allow two or more corrections const bool noCorrectionsHappenedSoFar = correctionCount == 0; const bool canTryCorrection = noCorrectionsHappenedSoFar; int proximityIndex = 0; mDistances[mOutputIndex] = NOT_A_DISTANCE; + // Skip checking this node if (mNeedsToTraverseAllNodes || isQuote(c)) { bool incremented = false; if (mLastCharExceeded && mInputIndex == mInputLength - 1) { @@ -342,6 +350,7 @@ Correction::CorrectionType Correction::processCharAndCalcState( return processSkipChar(c, isTerminal, incremented); } + // Check possible corrections. if (mExcessivePos >= 0) { if (mExcessiveCount == 0 && mExcessivePos < mOutputIndex) { mExcessivePos = mOutputIndex; @@ -382,30 +391,42 @@ Correction::CorrectionType Correction::processCharAndCalcState( incrementInputIndex(); } else { --mTransposedCount; - if (DEBUG_CORRECTION) { + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { DUMP_WORD(mWord, mOutputIndex); - LOGI("UNRELATED(0): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + AKLOGI("UNRELATED(0): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, mTransposedCount, mExcessiveCount, c); } - return UNRELATED; + return processUnrelatedCorrectionType(); } } // TODO: Change the limit if we'll allow two or more proximity chars with corrections - const bool checkProximityChars = noCorrectionsHappenedSoFar || mProximityCount == 0; + // Work around: When the mMaxErrors is 1, we only allow just one error + // including proximity correction. + const bool checkProximityChars = (mMaxErrors > 1) + ? (noCorrectionsHappenedSoFar || mProximityCount == 0) + : (noCorrectionsHappenedSoFar && mProximityCount == 0); + ProximityInfo::ProximityType matchedProximityCharId = secondTransposing ? ProximityInfo::EQUIVALENT_CHAR : mProximityInfo->getMatchedProximityId( mInputIndex, c, checkProximityChars, &proximityIndex); - if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) { + if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId + || ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) { if (canTryCorrection && mOutputIndex > 0 && mCorrectionStates[mOutputIndex].mProximityMatching && mCorrectionStates[mOutputIndex].mExceeding && isEquivalentChar(mProximityInfo->getMatchedProximityId( mInputIndex, mWord[mOutputIndex - 1], false))) { - if (DEBUG_CORRECTION) { - LOGI("CONVERSION p->e %c", mWord[mOutputIndex - 1]); + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { + AKLOGI("CONVERSION p->e %c", mWord[mOutputIndex - 1]); } // Conversion p->e // Example: @@ -423,7 +444,11 @@ Correction::CorrectionType Correction::processCharAndCalcState( } } - if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) { + if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId + || ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) { + if (ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) { + mAdditionalProximityMatching = true; + } // TODO: Optimize // As the current char turned out to be an unrelated char, // we will try other correction-types. Please note that mCorrectionStates[mOutputIndex] @@ -465,6 +490,18 @@ Correction::CorrectionType Correction::processCharAndCalcState( ++mSkippedCount; --mProximityCount; return processSkipChar(c, isTerminal, false); + } else if (mInputIndex - 1 < mInputLength + && mSkippedCount > 0 + && mCorrectionStates[mOutputIndex].mSkipping + && mCorrectionStates[mOutputIndex].mAdditionalProximityMatching + && isProximityCharOrEquivalentChar( + mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) { + // Conversion s->a + incrementInputIndex(); + --mSkippedCount; + mProximityMatching = true; + ++mProximityCount; + mDistances[mOutputIndex] = ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO; } else if ((mExceeding || mTransposing) && mInputIndex - 1 < mInputLength && isEquivalentChar( mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) { @@ -475,17 +512,52 @@ Correction::CorrectionType Correction::processCharAndCalcState( ++mExcessiveCount; incrementInputIndex(); } + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { + DUMP_WORD(mWord, mOutputIndex); + if (mTransposing) { + AKLOGI("TRANSPOSE: %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + mTransposedCount, mExcessiveCount, c); + } else { + AKLOGI("EXCEED: %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + mTransposedCount, mExcessiveCount, c); + } + } } else if (mSkipping) { // 3. Skip correction ++mSkippedCount; + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { + AKLOGI("SKIP: %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + mTransposedCount, mExcessiveCount, c); + } return processSkipChar(c, isTerminal, false); + } else if (ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) { + // As a last resort, use additional proximity characters + mProximityMatching = true; + ++mProximityCount; + mDistances[mOutputIndex] = ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO; + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { + AKLOGI("ADDITIONALPROX: %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + mTransposedCount, mExcessiveCount, c); + } } else { - if (DEBUG_CORRECTION) { + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { DUMP_WORD(mWord, mOutputIndex); - LOGI("UNRELATED(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + AKLOGI("UNRELATED(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, mTransposedCount, mExcessiveCount, c); } - return UNRELATED; + return processUnrelatedCorrectionType(); } } else if (secondTransposing) { // If inputIndex is greater than mInputLength, that means there is no @@ -500,6 +572,13 @@ Correction::CorrectionType Correction::processCharAndCalcState( ++mProximityCount; mDistances[mOutputIndex] = mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex); + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 + || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { + AKLOGI("PROX: %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + mTransposedCount, mExcessiveCount, c); + } } addCharToCurrentWord(c); @@ -533,13 +612,17 @@ Correction::CorrectionType Correction::processCharAndCalcState( || isSameAsUserTypedLength) && isTerminal) { mTerminalInputIndex = mInputIndex - 1; mTerminalOutputIndex = mOutputIndex - 1; - if (DEBUG_CORRECTION) { + if (DEBUG_CORRECTION + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength) + && (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0 || MIN_OUTPUT_INDEX_FOR_DEBUG < mOutputIndex)) { DUMP_WORD(mWord, mOutputIndex); - LOGI("ONTERMINAL(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, + AKLOGI("ONTERMINAL(1): %d, %d, %d, %d, %c", mProximityCount, mSkippedCount, mTransposedCount, mExcessiveCount, c); } return ON_TERMINAL; } else { + mTerminalInputIndex = mInputIndex - 1; + mTerminalOutputIndex = mOutputIndex - 1; return NOT_ON_TERMINAL; } } @@ -547,55 +630,6 @@ Correction::CorrectionType Correction::processCharAndCalcState( Correction::~Correction() { } -///////////////////////// -// static inline utils // -///////////////////////// - -static const int TWO_31ST_DIV_255 = S_INT_MAX / 255; -static inline int capped255MultForFullMatchAccentsOrCapitalizationDifference(const int num) { - return (num < TWO_31ST_DIV_255 ? 255 * num : S_INT_MAX); -} - -static const int TWO_31ST_DIV_2 = S_INT_MAX / 2; -inline static void multiplyIntCapped(const int multiplier, int *base) { - const int temp = *base; - if (temp != S_INT_MAX) { - // Branch if multiplier == 2 for the optimization - if (multiplier == 2) { - *base = TWO_31ST_DIV_2 >= temp ? temp << 1 : S_INT_MAX; - } else { - // TODO: This overflow check gives a wrong answer when, for example, - // temp = 2^16 + 1 and multiplier = 2^17 + 1. - // Fix this behavior. - const int tempRetval = temp * multiplier; - *base = tempRetval >= temp ? tempRetval : S_INT_MAX; - } - } -} - -inline static int powerIntCapped(const int base, const int n) { - if (n <= 0) return 1; - if (base == 2) { - return n < 31 ? 1 << n : S_INT_MAX; - } else { - int ret = base; - for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); - return ret; - } -} - -inline static void multiplyRate(const int rate, int *freq) { - if (*freq != S_INT_MAX) { - if (*freq > 1000000) { - *freq /= 100; - multiplyIntCapped(rate, freq); - } else { - multiplyIntCapped(rate, freq); - *freq /= 100; - } - } -} - inline static int getQuoteCount(const unsigned short* word, const int length) { int quoteCount = 0; for (int i = 0; i < length; ++i) { @@ -607,13 +641,7 @@ inline static int getQuoteCount(const unsigned short* word, const int length) { } inline static bool isUpperCase(unsigned short c) { - if (c < sizeof(BASE_CHARS) / sizeof(BASE_CHARS[0])) { - c = BASE_CHARS[c]; - } - if (isupper(c)) { - return true; - } - return false; + return isAsciiUpper(toBaseChar(c)); } ////////////////////// @@ -622,9 +650,9 @@ inline static bool isUpperCase(unsigned short c) { /* static */ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const int outputIndex, - const int freq, int* editDistanceTable, const Correction* correction) { + const int freq, int* editDistanceTable, const Correction* correction, + const int inputLength) { const int excessivePos = correction->getExcessivePos(); - const int inputLength = correction->mInputLength; const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER; const int fullWordMultiplier = correction->FULL_WORD_MULTIPLIER; const ProximityInfo *proximityInfo = correction->mProximityInfo; @@ -649,45 +677,55 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const const unsigned short* word = correction->mWord; const bool skipped = skippedCount > 0; - const int quoteDiffCount = max(0, getQuoteCount(word, outputIndex + 1) + const int quoteDiffCount = max(0, getQuoteCount(word, outputLength) - getQuoteCount(proximityInfo->getPrimaryInputWord(), inputLength)); // TODO: Calculate edit distance for transposed and excessive int ed = 0; + if (DEBUG_DICT_FULL) { + dumpEditDistance10ForDebug(editDistanceTable, correction->mInputLength, outputLength); + } int adjustedProximityMatchedCount = proximityMatchedCount; int finalFreq = freq; + if (DEBUG_CORRECTION_FREQ + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == inputLength)) { + AKLOGI("FinalFreq0: %d", finalFreq); + } // TODO: Optimize this. - // TODO: Ignoring edit distance for transposed char, for now - if (transposedCount == 0 && (proximityMatchedCount > 0 || skipped || excessiveCount > 0)) { - ed = getCurrentEditDistance(editDistanceTable, inputLength, outputIndex + 1); + if (transposedCount > 0 || proximityMatchedCount > 0 || skipped || excessiveCount > 0) { + ed = getCurrentEditDistance(editDistanceTable, correction->mInputLength, outputLength, + inputLength) - transposedCount; + const int matchWeight = powerIntCapped(typedLetterMultiplier, - max(inputLength, outputIndex + 1) - ed); + max(inputLength, outputLength) - ed); multiplyIntCapped(matchWeight, &finalFreq); // TODO: Demote further if there are two or more excessive chars with longer user input? - if (inputLength > outputIndex + 1) { + if (inputLength > outputLength) { multiplyRate(INPUT_EXCEEDS_OUTPUT_DEMOTION_RATE, &finalFreq); } ed = max(0, ed - quoteDiffCount); - - if (ed == 1 && (inputLength == outputIndex || inputLength == outputIndex + 2)) { - // Promote a word with just one skipped or excessive char - if (sameLength) { - multiplyRate(WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_RATE, &finalFreq); - } else { + adjustedProximityMatchedCount = min(max(0, ed - (outputLength - inputLength)), + proximityMatchedCount); + if (transposedCount < 1) { + if (ed == 1 && (inputLength == outputLength - 1 || inputLength == outputLength + 1)) { + // Promote a word with just one skipped or excessive char + if (sameLength) { + multiplyRate(WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_RATE + + WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_MULTIPLIER * outputLength, + &finalFreq); + } else { + multiplyIntCapped(typedLetterMultiplier, &finalFreq); + } + } else if (ed == 0) { multiplyIntCapped(typedLetterMultiplier, &finalFreq); + sameLength = true; } - } else if (ed == 0) { - multiplyIntCapped(typedLetterMultiplier, &finalFreq); - sameLength = true; } - adjustedProximityMatchedCount = min(max(0, ed - (outputIndex + 1 - inputLength)), - proximityMatchedCount); } else { - // TODO: Calculate the edit distance for transposed char const int matchWeight = powerIntCapped(typedLetterMultiplier, matchCount); multiplyIntCapped(matchWeight, &finalFreq); } @@ -707,7 +745,7 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const / (10 * inputLength - WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X + 10); if (DEBUG_DICT_FULL) { - LOGI("Demotion rate for missing character is %d.", demotionRate); + AKLOGI("Demotion rate for missing character is %d.", demotionRate); } multiplyRate(demotionRate, &finalFreq); } @@ -720,8 +758,8 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const if (excessiveCount > 0) { multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq); if (!lastCharExceeded && !proximityInfo->existsAdjacentProximityChars(excessivePos)) { - if (DEBUG_CORRECTION_FREQ) { - LOGI("Double excessive demotion"); + if (DEBUG_DICT_FULL) { + AKLOGI("Double excessive demotion"); } // If an excessive character is not adjacent to the left char or the right char, // we will demote this word. @@ -729,11 +767,14 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const } } + const bool performTouchPositionCorrection = + CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfo->touchPositionCorrectionEnabled() + && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0; // Score calibration by touch coordinates is being done only for pure-fat finger typing error // cases. + int additionalProximityCount = 0; // TODO: Remove this constraint. - if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfo->touchPositionCorrectionEnabled() - && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0) { + if (performTouchPositionCorrection) { for (int i = 0; i < outputLength; ++i) { const int squaredDistance = correction->mDistances[i]; if (i < adjustedProximityMatchedCount) { @@ -744,40 +785,60 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const static const float A = ZERO_DISTANCE_PROMOTION_RATE / 100.0f; static const float B = 1.0f; static const float C = 0.5f; + static const float MIN = 0.3f; static const float R1 = NEUTRAL_SCORE_SQUARED_RADIUS; static const float R2 = HALF_SCORE_SQUARED_RADIUS; const float x = (float)squaredDistance / ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR; - const float factor = (x < R1) + const float factor = max((x < R1) ? (A * (R1 - x) + B * x) / R1 - : (B * (R2 - x) + C * (x - R1)) / (R2 - R1); + : (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN); // factor is piecewise linear function like: // A -_ . // ^-_ . // B \ . - // \ . - // C \ . - // 0 R1 R2 - if (factor <= 0) { - return -1; - } + // \_ . + // C ------------. + // . + // 0 R1 R2 . multiplyRate((int)(factor * 100), &finalFreq); } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) { multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); + } else if (squaredDistance == ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO) { + ++additionalProximityCount; + multiplyRate(WORDS_WITH_ADDITIONAL_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); } } } else { + // Demote additional proximity characters + for (int i = 0; i < outputLength; ++i) { + const int squaredDistance = correction->mDistances[i]; + if (squaredDistance == ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO) { + ++additionalProximityCount; + } + } // Promotion for a word with proximity characters for (int i = 0; i < adjustedProximityMatchedCount; ++i) { // A word with proximity corrections if (DEBUG_DICT_FULL) { - LOGI("Found a proximity correction."); + AKLOGI("Found a proximity correction."); } multiplyIntCapped(typedLetterMultiplier, &finalFreq); - multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); + if (i < additionalProximityCount) { + multiplyRate(WORDS_WITH_ADDITIONAL_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); + } else { + multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); + } } } + // If the user types too many(three or more) proximity characters with additional proximity + // character,do not treat as the same length word. + if (sameLength && additionalProximityCount > 0 && (adjustedProximityMatchedCount >= 3 + || transposedCount > 0 || skipped || excessiveCount > 0)) { + sameLength = false; + } + const int errorCount = adjustedProximityMatchedCount > 0 ? adjustedProximityMatchedCount : (proximityMatchedCount + transposedCount); @@ -787,13 +848,15 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const // Promotion for an exactly matched word if (ed == 0) { // Full exact match - if (sameLength && transposedCount == 0 && !skipped && excessiveCount == 0) { + if (sameLength && transposedCount == 0 && !skipped && excessiveCount == 0 + && quoteDiffCount == 0 && additionalProximityCount == 0) { finalFreq = capped255MultForFullMatchAccentsOrCapitalizationDifference(finalFreq); } } // Promote a word with no correction - if (proximityMatchedCount == 0 && transposedCount == 0 && !skipped && excessiveCount == 0) { + if (proximityMatchedCount == 0 && transposedCount == 0 && !skipped && excessiveCount == 0 + && additionalProximityCount == 0) { multiplyRate(FULL_MATCHED_WORDS_PROMOTION_RATE, &finalFreq); } @@ -832,71 +895,101 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const } if (DEBUG_DICT_FULL) { - LOGI("calc: %d, %d", outputIndex, sameLength); + AKLOGI("calc: %d, %d", outputLength, sameLength); } - if (DEBUG_CORRECTION_FREQ) { - DUMP_WORD(correction->mWord, outputIndex + 1); - LOGI("FinalFreq: [P%d, S%d, T%d, E%d] %d, %d, %d, %d, %d", proximityMatchedCount, - skippedCount, transposedCount, excessiveCount, lastCharExceeded, sameLength, - quoteDiffCount, ed, finalFreq); + if (DEBUG_CORRECTION_FREQ + && (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == inputLength)) { + DUMP_WORD(proximityInfo->getPrimaryInputWord(), inputLength); + DUMP_WORD(correction->mWord, outputLength); + AKLOGI("FinalFreq: [P%d, S%d, T%d, E%d, A%d] %d, %d, %d, %d, %d, %d", proximityMatchedCount, + skippedCount, transposedCount, excessiveCount, additionalProximityCount, + outputLength, lastCharExceeded, sameLength, quoteDiffCount, ed, finalFreq); } return finalFreq; } /* static */ -int Correction::RankingAlgorithm::calcFreqForSplitTwoWords( - const int firstFreq, const int secondFreq, const Correction* correction, - const unsigned short *word) { - const int spaceProximityPos = correction->mSpaceProximityPos; - const int missingSpacePos = correction->mMissingSpacePos; - if (DEBUG_DICT) { - int inputCount = 0; - if (spaceProximityPos >= 0) ++inputCount; - if (missingSpacePos >= 0) ++inputCount; - assert(inputCount <= 1); - } - const bool isSpaceProximity = spaceProximityPos >= 0; - const int inputLength = correction->mInputLength; - const int firstWordLength = isSpaceProximity ? spaceProximityPos : missingSpacePos; - const int secondWordLength = isSpaceProximity ? (inputLength - spaceProximityPos - 1) - : (inputLength - missingSpacePos); +int Correction::RankingAlgorithm::calcFreqForSplitMultipleWords( + const int *freqArray, const int *wordLengthArray, const int wordCount, + const Correction* correction, const bool isSpaceProximity, const unsigned short *word) { const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER; bool firstCapitalizedWordDemotion = false; - if (firstWordLength >= 2) { - firstCapitalizedWordDemotion = isUpperCase(word[0]); - } - bool secondCapitalizedWordDemotion = false; - if (secondWordLength >= 2) { - secondCapitalizedWordDemotion = isUpperCase(word[firstWordLength + 1]); + + { + // TODO: Handle multiple capitalized word demotion properly + const int firstWordLength = wordLengthArray[0]; + const int secondWordLength = wordLengthArray[1]; + if (firstWordLength >= 2) { + firstCapitalizedWordDemotion = isUpperCase(word[0]); + } + + if (secondWordLength >= 2) { + // FIXME: word[firstWordLength + 1] is incorrect. + secondCapitalizedWordDemotion = isUpperCase(word[firstWordLength + 1]); + } } + const bool capitalizedWordDemotion = firstCapitalizedWordDemotion ^ secondCapitalizedWordDemotion; - if (DEBUG_DICT_FULL) { - LOGI("Two words: %c, %c, %d", word[0], word[firstWordLength + 1], capitalizedWordDemotion); + int totalLength = 0; + int totalFreq = 0; + for (int i = 0; i < wordCount; ++i){ + const int wordLength = wordLengthArray[i]; + if (wordLength <= 0) { + return 0; + } + totalLength += wordLength; + const int demotionRate = 100 - TWO_WORDS_CORRECTION_DEMOTION_BASE / (wordLength + 1); + int tempFirstFreq = freqArray[i]; + multiplyRate(demotionRate, &tempFirstFreq); + totalFreq += tempFirstFreq; } - if (firstWordLength == 0 || secondWordLength == 0) { + if (totalLength <= 0 || totalFreq <= 0) { return 0; } - const int firstDemotionRate = 100 - 100 / (firstWordLength + 1); - int tempFirstFreq = firstFreq; - multiplyRate(firstDemotionRate, &tempFirstFreq); - - const int secondDemotionRate = 100 - 100 / (secondWordLength + 1); - int tempSecondFreq = secondFreq; - multiplyRate(secondDemotionRate, &tempSecondFreq); - - const int totalLength = firstWordLength + secondWordLength; + // TODO: Currently totalFreq is adjusted to two word metrix. // Promote pairFreq with multiplying by 2, because the word length is the same as the typed // length. - int totalFreq = tempFirstFreq + tempSecondFreq; + totalFreq = totalFreq * 2 / wordCount; + if (wordCount > 2) { + // Safety net for 3+ words -- Caveats: many heuristics and workarounds here. + int oneLengthCounter = 0; + int twoLengthCounter = 0; + for (int i = 0; i < wordCount; ++i) { + const int wordLength = wordLengthArray[i]; + // TODO: Use bigram instead of this safety net + if (i < wordCount - 1) { + const int nextWordLength = wordLengthArray[i + 1]; + if (wordLength == 1 && nextWordLength == 2) { + // Safety net to filter 1 length and 2 length sequential words + return 0; + } + } + const int freq = freqArray[i]; + // Demote too short weak words + if (wordLength <= 4 && freq <= MAX_FREQ * 2 / 3 /* heuristic... */) { + multiplyRate(100 * freq / MAX_FREQ, &totalFreq); + } + if (wordLength == 1) { + ++oneLengthCounter; + } else if (wordLength == 2) { + ++twoLengthCounter; + } + if (oneLengthCounter >= 2 || (oneLengthCounter + twoLengthCounter) >= 4) { + // Safety net to filter too many short words + return 0; + } + } + multiplyRate(MULTIPLE_WORDS_DEMOTION_RATE, &totalFreq); + } // This is a workaround to try offsetting the not-enough-demotion which will be done in // calcNormalizedScore in Utils.java. @@ -923,19 +1016,128 @@ int Correction::RankingAlgorithm::calcFreqForSplitTwoWords( if (isSpaceProximity) { // A word pair with one space proximity correction if (DEBUG_DICT) { - LOGI("Found a word pair with space proximity correction."); + AKLOGI("Found a word pair with space proximity correction."); } multiplyIntCapped(typedLetterMultiplier, &totalFreq); multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &totalFreq); } - multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &totalFreq); + if (isSpaceProximity) { + multiplyRate(WORDS_WITH_MISTYPED_SPACE_DEMOTION_RATE, &totalFreq); + } else { + multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &totalFreq); + } if (capitalizedWordDemotion) { multiplyRate(TWO_WORDS_CAPITALIZED_DEMOTION_RATE, &totalFreq); } + if (DEBUG_CORRECTION_FREQ) { + AKLOGI("Multiple words (%d, %d) (%d, %d) %d, %d", freqArray[0], freqArray[1], + wordLengthArray[0], wordLengthArray[1], capitalizedWordDemotion, totalFreq); + DUMP_WORD(word, wordLengthArray[0]); + } + return totalFreq; } +/* Damerau-Levenshtein distance */ +inline static int editDistanceInternal( + int* editDistanceTable, const unsigned short* before, + const int beforeLength, const unsigned short* after, const int afterLength) { + // dp[li][lo] dp[a][b] = dp[ a * lo + b] + int* dp = editDistanceTable; + const int li = beforeLength + 1; + const int lo = afterLength + 1; + for (int i = 0; i < li; ++i) { + dp[lo * i] = i; + } + for (int i = 0; i < lo; ++i) { + dp[i] = i; + } + + for (int i = 0; i < li - 1; ++i) { + for (int j = 0; j < lo - 1; ++j) { + const uint32_t ci = toBaseLowerCase(before[i]); + const uint32_t co = toBaseLowerCase(after[j]); + const uint16_t cost = (ci == co) ? 0 : 1; + dp[(i + 1) * lo + (j + 1)] = min(dp[i * lo + (j + 1)] + 1, + min(dp[(i + 1) * lo + j] + 1, dp[i * lo + j] + cost)); + if (i > 0 && j > 0 && ci == toBaseLowerCase(after[j - 1]) + && co == toBaseLowerCase(before[i - 1])) { + dp[(i + 1) * lo + (j + 1)] = min( + dp[(i + 1) * lo + (j + 1)], dp[(i - 1) * lo + (j - 1)] + cost); + } + } + } + + if (DEBUG_EDIT_DISTANCE) { + AKLOGI("IN = %d, OUT = %d", beforeLength, afterLength); + for (int i = 0; i < li; ++i) { + for (int j = 0; j < lo; ++j) { + AKLOGI("EDIT[%d][%d], %d", i, j, dp[i * lo + j]); + } + } + } + return dp[li * lo - 1]; +} + +int Correction::RankingAlgorithm::editDistance(const unsigned short* before, + const int beforeLength, const unsigned short* after, const int afterLength) { + int table[(beforeLength + 1) * (afterLength + 1)]; + return editDistanceInternal(table, before, beforeLength, after, afterLength); +} + + +// In dictionary.cpp, getSuggestion() method, +// suggestion scores are computed using the below formula. +// original score +// := pow(mTypedLetterMultiplier (this is defined 2), +// (the number of matched characters between typed word and suggested word)) +// * (individual word's score which defined in the unigram dictionary, +// and this score is defined in range [0, 255].) +// Then, the following processing is applied. +// - If the dictionary word is matched up to the point of the user entry +// (full match up to min(before.length(), after.length()) +// => Then multiply by FULL_MATCHED_WORDS_PROMOTION_RATE (this is defined 1.2) +// - If the word is a true full match except for differences in accents or +// capitalization, then treat it as if the score was 255. +// - If before.length() == after.length() +// => multiply by mFullWordMultiplier (this is defined 2)) +// So, maximum original score is pow(2, min(before.length(), after.length())) * 255 * 2 * 1.2 +// For historical reasons we ignore the 1.2 modifier (because the measure for a good +// autocorrection threshold was done at a time when it didn't exist). This doesn't change +// the result. +// So, we can normalize original score by dividing pow(2, min(b.l(),a.l())) * 255 * 2. + +/* static */ +double Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short* before, + const int beforeLength, const unsigned short* after, const int afterLength, + const int score) { + if (0 == beforeLength || 0 == afterLength) { + return 0; + } + const int distance = editDistance(before, beforeLength, after, afterLength); + int spaceCount = 0; + for (int i = 0; i < afterLength; ++i) { + if (after[i] == CODE_SPACE) { + ++spaceCount; + } + } + + if (spaceCount == afterLength) { + return 0; + } + + const double maxScore = score >= S_INT_MAX ? S_INT_MAX : MAX_INITIAL_SCORE + * pow((double)TYPED_LETTER_MULTIPLIER, + (double)min(beforeLength, afterLength - spaceCount)) * FULL_WORD_MULTIPLIER; + + // add a weight based on edit distance. + // distance <= max(afterLength, beforeLength) == afterLength, + // so, 0 <= distance / afterLength <= 1 + const double weight = 1.0 - (double) distance / afterLength; + return (score / maxScore) * weight; +} + } // namespace latinime diff --git a/native/src/correction.h b/native/src/correction.h index d4e99f0ce..ee55c9604 100644 --- a/native/src/correction.h +++ b/native/src/correction.h @@ -17,6 +17,7 @@ #ifndef LATINIME_CORRECTION_H #define LATINIME_CORRECTION_H +#include <assert.h> #include <stdint.h> #include "correction_state.h" @@ -27,8 +28,7 @@ namespace latinime { class ProximityInfo; class Correction { - -public: + public: typedef enum { TRAVERSE_ALL_ON_TERMINAL, TRAVERSE_ALL_NOT_ON_TERMINAL, @@ -37,6 +37,62 @@ public: NOT_ON_TERMINAL } CorrectionType; + ///////////////////////// + // static inline utils // + ///////////////////////// + + static const int TWO_31ST_DIV_255 = S_INT_MAX / 255; + static inline int capped255MultForFullMatchAccentsOrCapitalizationDifference(const int num) { + return (num < TWO_31ST_DIV_255 ? 255 * num : S_INT_MAX); + } + + static const int TWO_31ST_DIV_2 = S_INT_MAX / 2; + inline static void multiplyIntCapped(const int multiplier, int *base) { + const int temp = *base; + if (temp != S_INT_MAX) { + // Branch if multiplier == 2 for the optimization + if (multiplier < 0) { + if (DEBUG_DICT) { + assert(false); + } + AKLOGI("--- Invalid multiplier: %d", multiplier); + } else if (multiplier == 0) { + *base = 0; + } else if (multiplier == 2) { + *base = TWO_31ST_DIV_2 >= temp ? temp << 1 : S_INT_MAX; + } else { + // TODO: This overflow check gives a wrong answer when, for example, + // temp = 2^16 + 1 and multiplier = 2^17 + 1. + // Fix this behavior. + const int tempRetval = temp * multiplier; + *base = tempRetval >= temp ? tempRetval : S_INT_MAX; + } + } + } + + inline static int powerIntCapped(const int base, const int n) { + if (n <= 0) return 1; + if (base == 2) { + return n < 31 ? 1 << n : S_INT_MAX; + } else { + int ret = base; + for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); + return ret; + } + } + + inline static void multiplyRate(const int rate, int *freq) { + if (*freq != S_INT_MAX) { + if (*freq > 1000000) { + *freq /= 100; + multiplyIntCapped(rate, freq); + } else { + multiplyIntCapped(rate, freq); + *freq /= 100; + } + } + } + Correction(const int typedLetterMultiplier, const int fullWordMultiplier); void initCorrection( const ProximityInfo *pi, const int inputLength, const int maxWordLength); @@ -44,11 +100,11 @@ public: // TODO: remove void setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos, - const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance); + const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance, + const bool doAutoCompletion, const int maxErrors); void checkState(); bool initProcessState(const int index); - int getOutputIndex(); int getInputIndex(); virtual ~Correction(); @@ -73,9 +129,12 @@ public: bool needsToPrune() const; - int getFreqForSplitTwoWords( - const int firstFreq, const int secondFreq, const unsigned short *word); + int getFreqForSplitMultipleWords( + const int *freqArray, const int *wordLengthArray, const int wordCount, + const bool isSpaceProximity, const unsigned short *word); int getFinalFreq(const int freq, unsigned short **word, int* wordLength); + int getFinalFreqForSubQueue(const int freq, unsigned short **word, int* wordLength, + const int inputLength); CorrectionType processCharAndCalcState(const int32_t c, const bool isTerminal); @@ -94,21 +153,44 @@ public: inline int getTreeParentIndex(const int index) const { return mCorrectionStates[index].mParentIndex; } -private: + + class RankingAlgorithm { + public: + static int calculateFinalFreq(const int inputIndex, const int depth, + const int freq, int *editDistanceTable, const Correction* correction, + const int inputLength); + static int calcFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, + const int wordCount, const Correction* correction, const bool isSpaceProximity, + const unsigned short *word); + static double calcNormalizedScore(const unsigned short* before, const int beforeLength, + const unsigned short* after, const int afterLength, const int score); + static int editDistance(const unsigned short* before, + const int beforeLength, const unsigned short* after, const int afterLength); + private: + static const int CODE_SPACE = ' '; + static const int MAX_INITIAL_SCORE = 255; + static const int TYPED_LETTER_MULTIPLIER = 2; + static const int FULL_WORD_MULTIPLIER = 2; + }; + + private: inline void incrementInputIndex(); inline void incrementOutputIndex(); - inline bool needsToTraverseAllNodes(); inline void startToTraverseAllNodes(); inline bool isQuote(const unsigned short c); inline CorrectionType processSkipChar( const int32_t c, const bool isTerminal, const bool inputIndexIncremented); + inline CorrectionType processUnrelatedCorrectionType(); inline void addCharToCurrentWord(const int32_t c); + inline int getFinalFreqInternal(const int freq, unsigned short **word, int* wordLength, + const int inputLength); const int TYPED_LETTER_MULTIPLIER; const int FULL_WORD_MULTIPLIER; const ProximityInfo *mProximityInfo; bool mUseFullEditDistance; + bool mDoAutoCompletion; int mMaxEditDistance; int mMaxDepth; int mInputLength; @@ -116,6 +198,7 @@ private: int mMissingSpacePos; int mTerminalInputIndex; int mTerminalOutputIndex; + int mMaxErrors; // The following arrays are state buffer. unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; @@ -146,17 +229,11 @@ private: bool mMatching; bool mProximityMatching; + bool mAdditionalProximityMatching; bool mExceeding; bool mTransposing; bool mSkipping; - class RankingAlgorithm { - public: - static int calculateFinalFreq(const int inputIndex, const int depth, - const int freq, int *editDistanceTable, const Correction* correction); - static int calcFreqForSplitTwoWords(const int firstFreq, const int secondFreq, - const Correction* correction, const unsigned short *word); - }; }; } // namespace latinime #endif // LATINIME_CORRECTION_H diff --git a/native/src/correction_state.h b/native/src/correction_state.h index c04146e54..5b2cbd3a2 100644 --- a/native/src/correction_state.h +++ b/native/src/correction_state.h @@ -47,9 +47,9 @@ struct CorrectionState { bool mExceeding; bool mSkipping; bool mProximityMatching; + bool mAdditionalProximityMatching; bool mNeedsToTraverseAllNodes; - }; inline static void initCorrectionState(CorrectionState *state, const int rootPos, @@ -77,7 +77,7 @@ inline static void initCorrectionState(CorrectionState *state, const int rootPos state->mTransposing = false; state->mExceeding = false; state->mSkipping = false; - + state->mAdditionalProximityMatching = false; } } // namespace latinime diff --git a/native/src/debug.h b/native/src/debug.h index 38b2f107a..b13052c95 100644 --- a/native/src/debug.h +++ b/native/src/debug.h @@ -42,7 +42,7 @@ static inline unsigned char* convertToUnibyteStringAndReplaceLastChar(unsigned s static inline void LOGI_S16(unsigned short* string, const unsigned int length) { unsigned char tmp_buffer[length]; convertToUnibyteString(string, tmp_buffer, length); - LOGI(">> %s", tmp_buffer); + AKLOGI(">> %s", tmp_buffer); // The log facility is throwing out log that comes too fast. The following // is a dirty way of slowing down processing so that we can see all log. // TODO : refactor this in a blocking log or something. @@ -53,7 +53,7 @@ static inline void LOGI_S16_PLUS(unsigned short* string, const unsigned int leng unsigned char c) { unsigned char tmp_buffer[length+1]; convertToUnibyteStringAndReplaceLastChar(string, tmp_buffer, length, c); - LOGI(">> %s", tmp_buffer); + AKLOGI(">> %s", tmp_buffer); // Likewise // usleep(10); } @@ -64,7 +64,7 @@ static inline void printDebug(const char* tag, int* codes, int codesSize, int MA buf[codesSize] = 0; while (--codesSize >= 0) buf[codesSize] = (unsigned char)codes[codesSize * MAX_PROXIMITY_CHARS]; - LOGI("%s, WORD = %s", tag, buf); + AKLOGI("%s, WORD = %s", tag, buf); free(buf); } diff --git a/native/src/defines.h b/native/src/defines.h index ef1beb92f..b0dbffa0f 100644 --- a/native/src/defines.h +++ b/native/src/defines.h @@ -20,15 +20,31 @@ #if defined(FLAG_DO_PROFILE) || defined(FLAG_DBG) #include <cutils/log.h> +#define AKLOGE ALOGE +#define AKLOGI ALOGI + +#define DUMP_WORD(word, length) do { dumpWord(word, length); } while(0) + +static inline void dumpWord(const unsigned short* word, const int length) { + static char charBuf[50]; + + for (int i = 0; i < length; ++i) { + charBuf[i] = word[i]; + } + charBuf[length] = 0; + AKLOGI("[ %s ]", charBuf); +} + #else -#define LOGE(fmt, ...) -#define LOGI(fmt, ...) +#define AKLOGE(fmt, ...) +#define AKLOGI(fmt, ...) +#define DUMP_WORD(word, length) #endif #ifdef FLAG_DO_PROFILE // Profiler -#include <cutils/log.h> #include <time.h> + #define PROF_BUF_SIZE 100 static double profile_buf[PROF_BUF_SIZE]; static double profile_old[PROF_BUF_SIZE]; @@ -42,10 +58,10 @@ static unsigned int profile_counter[PROF_BUF_SIZE]; #define PROF_CLOSE do { PROF_END(PROF_BUF_SIZE - 1); PROF_OUTALL; } while(0) #define PROF_END(prof_buf_id) profile_buf[prof_buf_id] += ((clock()) - profile_old[prof_buf_id]) #define PROF_CLOCKOUT(prof_buf_id) \ - LOGI("%s : clock is %f", __FUNCTION__, (clock() - profile_old[prof_buf_id])) -#define PROF_OUTALL do { LOGI("--- %s ---", __FUNCTION__); prof_out(); } while(0) + AKLOGI("%s : clock is %f", __FUNCTION__, (clock() - profile_old[prof_buf_id])) +#define PROF_OUTALL do { AKLOGI("--- %s ---", __FUNCTION__); prof_out(); } while(0) -static void prof_reset(void) { +static inline void prof_reset(void) { for (int i = 0; i < PROF_BUF_SIZE; ++i) { profile_buf[i] = 0; profile_old[i] = 0; @@ -53,11 +69,11 @@ static void prof_reset(void) { } } -static void prof_out(void) { +static inline void prof_out(void) { if (profile_counter[PROF_BUF_SIZE - 1] != 1) { - LOGI("Error: You must call PROF_OPEN before PROF_CLOSE."); + AKLOGI("Error: You must call PROF_OPEN before PROF_CLOSE."); } - LOGI("Total time is %6.3f ms.", + AKLOGI("Total time is %6.3f ms.", profile_buf[PROF_BUF_SIZE - 1] * 1000 / (double)CLOCKS_PER_SEC); double all = 0; for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) { @@ -66,7 +82,7 @@ static void prof_out(void) { if (all == 0) all = 1; for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) { if (profile_buf[i] != 0) { - LOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.", + AKLOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.", i, (profile_buf[i] * 100 / all), profile_buf[i] * 1000 / (double)CLOCKS_PER_SEC, profile_counter[i]); } @@ -98,21 +114,11 @@ static void prof_out(void) { #define DEBUG_SHOW_FOUND_WORD false #define DEBUG_NODE DEBUG_DICT_FULL #define DEBUG_TRACE DEBUG_DICT_FULL -#define DEBUG_PROXIMITY_INFO true +#define DEBUG_PROXIMITY_INFO false +#define DEBUG_PROXIMITY_CHARS false #define DEBUG_CORRECTION false -#define DEBUG_CORRECTION_FREQ true - -#define DUMP_WORD(word, length) do { dumpWord(word, length); } while(0) - -static char charBuf[50]; - -static void dumpWord(const unsigned short* word, const int length) { - for (int i = 0; i < length; ++i) { - charBuf[i] = word[i]; - } - charBuf[length] = 0; - LOGI("[ %s ]", charBuf); -} +#define DEBUG_CORRECTION_FREQ false +#define DEBUG_WORDS_PRIORITY_QUEUE false #else // FLAG_DBG @@ -123,10 +129,11 @@ static void dumpWord(const unsigned short* word, const int length) { #define DEBUG_NODE false #define DEBUG_TRACE false #define DEBUG_PROXIMITY_INFO false +#define DEBUG_PROXIMITY_CHARS false #define DEBUG_CORRECTION false #define DEBUG_CORRECTION_FREQ false +#define DEBUG_WORDS_PRIORITY_QUEUE false -#define DUMP_WORD(word, length) #endif // FLAG_DBG @@ -157,64 +164,91 @@ static void dumpWord(const unsigned short* word, const int length) { #define FLAG_BIGRAM_FREQ 0x7F #define DICTIONARY_VERSION_MIN 200 -// TODO: remove this constant when the switch to the new dict format is over -#define DICTIONARY_HEADER_SIZE 2 -#define NEW_DICTIONARY_HEADER_SIZE 5 #define NOT_VALID_WORD -99 #define NOT_A_CHARACTER -1 #define NOT_A_DISTANCE -1 +#define NOT_A_COORDINATE -1 #define EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO -2 #define PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO -3 +#define ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO -4 #define NOT_A_INDEX -1 +#define NOT_A_FREQUENCY -1 #define KEYCODE_SPACE ' ' #define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true #define SUGGEST_WORDS_WITH_MISSING_CHARACTER true -#define SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER true #define SUGGEST_WORDS_WITH_EXCESSIVE_CHARACTER true #define SUGGEST_WORDS_WITH_TRANSPOSED_CHARACTERS true -#define SUGGEST_WORDS_WITH_SPACE_PROXIMITY true +#define SUGGEST_MULTIPLE_WORDS true // The following "rate"s are used as a multiplier before dividing by 100, so they are in percent. #define WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE 80 #define WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X 12 -#define WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE 67 +#define WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE 58 +#define WORDS_WITH_MISTYPED_SPACE_DEMOTION_RATE 50 #define WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE 75 #define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75 -#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60 +#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 70 #define FULL_MATCHED_WORDS_PROMOTION_RATE 120 #define WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE 90 +#define WORDS_WITH_ADDITIONAL_PROXIMITY_CHARACTER_DEMOTION_RATE 70 #define WORDS_WITH_MATCH_SKIP_PROMOTION_RATE 105 -#define WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_RATE 160 +#define WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_RATE 148 +#define WORDS_WITH_JUST_ONE_CORRECTION_PROMOTION_MULTIPLIER 3 #define CORRECTION_COUNT_RATE_DEMOTION_RATE_BASE 45 #define INPUT_EXCEEDS_OUTPUT_DEMOTION_RATE 70 #define FIRST_CHAR_DIFFERENT_DEMOTION_RATE 96 #define TWO_WORDS_CAPITALIZED_DEMOTION_RATE 50 +#define TWO_WORDS_CORRECTION_DEMOTION_BASE 80 +#define TWO_WORDS_PLUS_OTHER_ERROR_CORRECTION_DEMOTION_DIVIDER 1 #define ZERO_DISTANCE_PROMOTION_RATE 110 #define NEUTRAL_SCORE_SQUARED_RADIUS 8.0f #define HALF_SCORE_SQUARED_RADIUS 32.0f +#define MAX_FREQ 255 -// This should be greater than or equal to MAX_WORD_LENGTH defined in BinaryDictionary.java +// This must be greater than or equal to MAX_WORD_LENGTH defined in BinaryDictionary.java // This is only used for the size of array. Not to be used in c functions. #define MAX_WORD_LENGTH_INTERNAL 48 +// This must be equal to ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE in KeyDetector.java +#define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2 + +// Word limit for sub queues used in WordsPriorityQueuePool. Sub queues are temporary queues used +// for better performance. +// Holds up to 1 candidate for each word +#define SUB_QUEUE_MAX_WORDS 1 +#define SUB_QUEUE_MAX_COUNT 10 +#define SUB_QUEUE_MIN_WORD_LENGTH 4 +#define MULTIPLE_WORDS_SUGGESTION_MAX_WORDS 10 +#define MULTIPLE_WORDS_DEMOTION_RATE 80 +#define MIN_INPUT_LENGTH_FOR_THREE_OR_MORE_WORDS_CORRECTION 6 + +#define TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD 0.39 +#define START_TWO_WORDS_CORRECTION_THRESHOLD 0.22 + #define MAX_DEPTH_MULTIPLIER 3 +#define FIRST_WORD_INDEX 0 + // TODO: Reduce this constant if possible; check the maximum number of umlauts in the same German // word in the dictionary #define DEFAULT_MAX_UMLAUT_SEARCH_DEPTH 5 // Minimum suggest depth for one word for all cases except for missing space suggestions. #define MIN_SUGGEST_DEPTH 1 -#define MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION 3 +#define MIN_USER_TYPED_LENGTH_FOR_MULTIPLE_WORD_SUGGESTION 3 #define MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION 3 -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) +template<typename T> inline T min(T a, T b) { return a < b ? a : b; } +template<typename T> inline T max(T a, T b) { return a > b ? a : b; } // The ratio of neutral area radius to sweet spot radius. #define NEUTRAL_AREA_RADIUS_RATIO 1.3f +// DEBUG +#define INPUTLENGTH_FOR_DEBUG -1 +#define MIN_OUTPUT_INDEX_FOR_DEBUG -1 + #endif // LATINIME_DEFINES_H diff --git a/native/src/dictionary.cpp b/native/src/dictionary.cpp index a49769bdb..8e252f730 100644 --- a/native/src/dictionary.cpp +++ b/native/src/dictionary.cpp @@ -19,6 +19,7 @@ #define LOG_TAG "LatinIME: dictionary.cpp" +#include "binary_format.h" #include "dictionary.h" namespace latinime { @@ -33,26 +34,28 @@ Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, IS_LATEST_DICT_VERSION((((unsigned char*) dict)[0] & 0xFF) >= DICTIONARY_VERSION_MIN) { if (DEBUG_DICT) { if (MAX_WORD_LENGTH_INTERNAL < maxWordLength) { - LOGI("Max word length (%d) is greater than %d", + AKLOGI("Max word length (%d) is greater than %d", maxWordLength, MAX_WORD_LENGTH_INTERNAL); - LOGI("IN NATIVE SUGGEST Version: %d", (mDict[0] & 0xFF)); + AKLOGI("IN NATIVE SUGGEST Version: %d", (mDict[0] & 0xFF)); } } - mUnigramDictionary = new UnigramDictionary(mDict, typedLetterMultiplier, fullWordMultiplier, - maxWordLength, maxWords, maxAlternatives, IS_LATEST_DICT_VERSION); - mBigramDictionary = new BigramDictionary(mDict, maxWordLength, maxAlternatives, - IS_LATEST_DICT_VERSION, hasBigram(), this); + mCorrection = new Correction(typedLetterMultiplier, fullWordMultiplier); + mWordsPriorityQueuePool = new WordsPriorityQueuePool( + maxWords, SUB_QUEUE_MAX_WORDS, maxWordLength); + const unsigned int headerSize = BinaryFormat::getHeaderSize(mDict); + mUnigramDictionary = new UnigramDictionary(mDict + headerSize, typedLetterMultiplier, + fullWordMultiplier, maxWordLength, maxWords, maxAlternatives, IS_LATEST_DICT_VERSION); + mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength, maxAlternatives, + IS_LATEST_DICT_VERSION, true /* hasBigram */, this); } Dictionary::~Dictionary() { + delete mCorrection; + delete mWordsPriorityQueuePool; delete mUnigramDictionary; delete mBigramDictionary; } -bool Dictionary::hasBigram() { - return ((mDict[1] & 0xFF) == 1); -} - bool Dictionary::isValidWord(unsigned short *word, int length) { return mUnigramDictionary->isValidWord(word, length); } diff --git a/native/src/dictionary.h b/native/src/dictionary.h index d5de0083a..90d7148d5 100644 --- a/native/src/dictionary.h +++ b/native/src/dictionary.h @@ -17,22 +17,25 @@ #ifndef LATINIME_DICTIONARY_H #define LATINIME_DICTIONARY_H -#include "basechars.h" #include "bigram_dictionary.h" #include "char_utils.h" +#include "correction.h" #include "defines.h" #include "proximity_info.h" #include "unigram_dictionary.h" +#include "words_priority_queue_pool.h" namespace latinime { class Dictionary { -public: + public: Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler, int fullWordMultiplier, int maxWordLength, int maxWords, int maxAlternatives); + int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, int *codes, int codesSize, int flags, unsigned short *outWords, int *frequencies) { - return mUnigramDictionary->getSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, + return mUnigramDictionary->getSuggestions(proximityInfo, mWordsPriorityQueuePool, + mCorrection, xcoordinates, ycoordinates, codes, codesSize, flags, outWords, frequencies); } @@ -53,19 +56,9 @@ public: // public static utility methods // static inline methods should be defined in the header file - static unsigned short getChar(const unsigned char *dict, int *pos); - static int getCount(const unsigned char *dict, int *pos); - static bool getTerminal(const unsigned char *dict, int *pos); - static int getAddress(const unsigned char *dict, int *pos); - static int getFreq(const unsigned char *dict, const bool isLatestDictVersion, int *pos); static int wideStrLen(unsigned short *str); - // returns next sibling's position - static int setDictionaryValues(const unsigned char *dict, const bool isLatestDictVersion, - const int pos, unsigned short *c, int *childrenPosition, - bool *terminal, int *freq); - static inline unsigned short toBaseLowerCase(unsigned short c); -private: + private: bool hasBigram(); const unsigned char *mDict; @@ -79,60 +72,12 @@ private: const bool IS_LATEST_DICT_VERSION; UnigramDictionary *mUnigramDictionary; BigramDictionary *mBigramDictionary; + WordsPriorityQueuePool *mWordsPriorityQueuePool; + Correction *mCorrection; }; // public static utility methods // static inline methods should be defined in the header file -inline unsigned short Dictionary::getChar(const unsigned char *dict, int *pos) { - unsigned short ch = (unsigned short) (dict[(*pos)++] & 0xFF); - // If the code is 255, then actual 16 bit code follows (in big endian) - if (ch == 0xFF) { - ch = ((dict[*pos] & 0xFF) << 8) | (dict[*pos + 1] & 0xFF); - (*pos) += 2; - } - return ch; -} - -inline int Dictionary::getCount(const unsigned char *dict, int *pos) { - return dict[(*pos)++] & 0xFF; -} - -inline bool Dictionary::getTerminal(const unsigned char *dict, int *pos) { - return (dict[*pos] & FLAG_TERMINAL_MASK) > 0; -} - -inline int Dictionary::getAddress(const unsigned char *dict, int *pos) { - int address = 0; - if ((dict[*pos] & FLAG_ADDRESS_MASK) == 0) { - *pos += 1; - } else { - address += (dict[*pos] & (ADDRESS_MASK >> 16)) << 16; - address += (dict[*pos + 1] & 0xFF) << 8; - address += (dict[*pos + 2] & 0xFF); - *pos += 3; - } - return address; -} - -inline int Dictionary::getFreq(const unsigned char *dict, - const bool isLatestDictVersion, int *pos) { - int freq = dict[(*pos)++] & 0xFF; - if (isLatestDictVersion) { - // skipping bigram - int bigramExist = (dict[*pos] & FLAG_BIGRAM_READ); - if (bigramExist > 0) { - int nextBigramExist = 1; - while (nextBigramExist > 0) { - (*pos) += 3; - nextBigramExist = (dict[(*pos)++] & FLAG_BIGRAM_CONTINUED); - } - } else { - (*pos)++; - } - } - return freq; -} - inline int Dictionary::wideStrLen(unsigned short *str) { if (!str) return 0; unsigned short *end = str; @@ -140,35 +85,6 @@ inline int Dictionary::wideStrLen(unsigned short *str) { end++; return end - str; } - -inline int Dictionary::setDictionaryValues(const unsigned char *dict, - const bool isLatestDictVersion, const int pos, unsigned short *c,int *childrenPosition, - bool *terminal, int *freq) { - int position = pos; - // -- at char - *c = Dictionary::getChar(dict, &position); - // -- at flag/add - *terminal = Dictionary::getTerminal(dict, &position); - *childrenPosition = Dictionary::getAddress(dict, &position); - // -- after address or flag - *freq = (*terminal) ? Dictionary::getFreq(dict, isLatestDictVersion, &position) : 1; - // returns next sibling's position - return position; -} - - -inline unsigned short Dictionary::toBaseLowerCase(unsigned short c) { - if (c < sizeof(BASE_CHARS) / sizeof(BASE_CHARS[0])) { - c = BASE_CHARS[c]; - } - if (c >='A' && c <= 'Z') { - c |= 32; - } else if (c > 127) { - c = latin_tolower(c); - } - return c; -} - } // namespace latinime #endif // LATINIME_DICTIONARY_H diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp index 763a3a174..dd60ed62c 100644 --- a/native/src/proximity_info.cpp +++ b/native/src/proximity_info.cpp @@ -16,10 +16,11 @@ #include <assert.h> #include <stdio.h> -#include <string.h> +#include <string> #define LOG_TAG "LatinIME: proximity_info.cpp" +#include "additional_proximity_chars.h" #include "dictionary.h" #include "proximity_info.h" @@ -33,26 +34,29 @@ inline void copyOrFillZero(void *to, const void *from, size_t size) { } } -ProximityInfo::ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth, - const int keyboardHeight, const int gridWidth, const int gridHeight, - const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates, +ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximityCharsSize, + const int keyboardWidth, const int keyboardHeight, const int gridWidth, + const int gridHeight, const int mostCommonKeyWidth, + const int32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates, const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights, const int32_t *keyCharCodes, const float *sweetSpotCenterXs, const float *sweetSpotCenterYs, const float *sweetSpotRadii) : MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize), KEYBOARD_WIDTH(keyboardWidth), KEYBOARD_HEIGHT(keyboardHeight), GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), + MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth), CELL_WIDTH((keyboardWidth + gridWidth - 1) / gridWidth), CELL_HEIGHT((keyboardHeight + gridHeight - 1) / gridHeight), KEY_COUNT(min(keyCount, MAX_KEY_COUNT_IN_A_KEYBOARD)), HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates && keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs && sweetSpotCenterYs && sweetSpotRadii), - mInputXCoordinates(NULL), mInputYCoordinates(NULL), + mLocaleStr(localeStr), + mInputXCoordinates(0), mInputYCoordinates(0), mTouchPositionCorrectionEnabled(false) { const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE; - mProximityCharsArray = new uint32_t[proximityGridLength]; + mProximityCharsArray = new int32_t[proximityGridLength]; if (DEBUG_PROXIMITY_INFO) { - LOGI("Create proximity info array %d", proximityGridLength); + AKLOGI("Create proximity info array %d", proximityGridLength); } memcpy(mProximityCharsArray, proximityCharsArray, proximityGridLength * sizeof(mProximityCharsArray[0])); @@ -100,13 +104,21 @@ inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) } bool ProximityInfo::hasSpaceProximity(const int x, const int y) const { + if (x < 0 || y < 0) { + if (DEBUG_DICT) { + AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y); + assert(false); + } + return false; + } + const int startIndex = getStartIndexFromCoordinates(x, y); if (DEBUG_PROXIMITY_INFO) { - LOGI("hasSpaceProximity: index %d", startIndex); + AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y); } for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { if (DEBUG_PROXIMITY_INFO) { - LOGI("Index: %d", mProximityCharsArray[startIndex + i]); + AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]); } if (mProximityCharsArray[startIndex + i] == KEYCODE_SPACE) { return true; @@ -115,6 +127,86 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const { return false; } +bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) { + const int left = mKeyXCoordinates[keyId]; + const int top = mKeyYCoordinates[keyId]; + const int right = left + mKeyWidths[keyId] + 1; + const int bottom = top + mKeyHeights[keyId]; + return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom; +} + +int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) { + const int left = mKeyXCoordinates[keyId]; + const int top = mKeyYCoordinates[keyId]; + const int right = left + mKeyWidths[keyId] + 1; + const int bottom = top + mKeyHeights[keyId]; + const int edgeX = x < left ? left : (x > right ? right : x); + const int edgeY = y < top ? top : (y > bottom ? bottom : y); + const int dx = x - edgeX; + const int dy = y - edgeY; + return dx * dx + dy * dy; +} + +void ProximityInfo::calculateNearbyKeyCodes( + const int x, const int y, const int32_t primaryKey, int *inputCodes) { + int insertPos = 0; + inputCodes[insertPos++] = primaryKey; + const int startIndex = getStartIndexFromCoordinates(x, y); + for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { + const int32_t c = mProximityCharsArray[startIndex + i]; + if (c < KEYCODE_SPACE || c == primaryKey) { + continue; + } + int keyIndex = getKeyIndex(c); + const bool onKey = isOnKey(keyIndex, x, y); + const int distance = squaredDistanceToEdge(keyIndex, x, y); + if (onKey || distance < MOST_COMMON_KEY_WIDTH_SQUARE) { + inputCodes[insertPos++] = c; + if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { + if (DEBUG_DICT) { + assert(false); + } + return; + } + } + } + inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { + if (DEBUG_DICT) { + assert(false); + } + return; + } + + const int additionalProximitySize = + AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey); + if (additionalProximitySize > 0) { + const int32_t* additionalProximityChars = + AdditionalProximityChars::getAdditionalChars(&mLocaleStr, primaryKey); + for (int j = 0; j < additionalProximitySize; ++j) { + const int32_t ac = additionalProximityChars[j]; + int k = 0; + for (; k < insertPos; ++k) { + if ((int)ac == inputCodes[k]) { + break; + } + } + if (k < insertPos) { + continue; + } + inputCodes[insertPos++] = ac; + if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { + if (DEBUG_DICT) { + assert(false); + } + return; + } + } + } + // Add a delimiter for the proximity characters + inputCodes[insertPos] = 0; +} + // TODO: Calculate nearby codes here. void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, const int* xCoordinates, const int* yCoordinates) { @@ -128,8 +220,30 @@ void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, mPrimaryInputWord[i] = getPrimaryCharAt(i); } mPrimaryInputWord[inputLength] = 0; + if (DEBUG_PROXIMITY_CHARS) { + AKLOGI("--- setInputParams"); + } for (int i = 0; i < mInputLength; ++i) { const int *proximityChars = getProximityCharsAt(i); + const int primaryKey = proximityChars[0]; + const int x = xCoordinates[i]; + const int y = yCoordinates[i]; + if (DEBUG_PROXIMITY_CHARS) { + int a = x + y + primaryKey; + a += 0; + AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y); + // Keep debug code just in case + //int proximities[50]; + //for (int m = 0; m < 50; ++m) { + //proximities[m] = 0; + //} + //calculateNearbyKeyCodes(x, y, primaryKey, proximities); + //for (int l = 0; l < 50 && proximities[l] > 0; ++l) { + //if (DEBUG_PROXIMITY_CHARS) { + //AKLOGI("--- native Proximity (%d) = %c", l, proximities[l]); + //} + //} + } for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) { const int currentChar = proximityChars[j]; const int keyIndex = getKeyIndex(currentChar); @@ -142,6 +256,9 @@ void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO : PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; } + if (DEBUG_PROXIMITY_CHARS) { + AKLOGI("--- Proximity (%d) = %c", j, currentChar); + } } } } @@ -157,6 +274,9 @@ float ProximityInfo::calculateNormalizedSquaredDistance( if (!hasSweetSpotData(keyIndex)) { return NOT_A_DISTANCE_FLOAT; } + if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) { + return NOT_A_DISTANCE_FLOAT; + } const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(keyIndex, inputIndex); const float squaredRadius = square(mSweetSpotRadii[keyIndex]); return squaredDistance / squaredRadius; @@ -167,7 +287,7 @@ int ProximityInfo::getKeyIndex(const int c) const { // We do not have the coordinate data return NOT_A_INDEX; } - const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c); + const unsigned short baseLowerC = toBaseLowerCase(c); if (baseLowerC > MAX_CHAR_CODE) { return NOT_A_INDEX; } @@ -232,7 +352,7 @@ ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(const int inde const unsigned short c, const bool checkProximityChars, int *proximityIndex) const { const int *currentChars = getProximityCharsAt(index); const int firstChar = currentChars[0]; - const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c); + const unsigned short baseLowerC = toBaseLowerCase(c); // The first char in the array is what user typed. If it matches right away, // that means the user typed that same char for this pos. @@ -245,12 +365,13 @@ ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(const int inde // If the non-accented, lowercased version of that first character matches c, // then we have a non-accented version of the accented character the user // typed. Treat it as a close char. - if (Dictionary::toBaseLowerCase(firstChar) == baseLowerC) + if (toBaseLowerCase(firstChar) == baseLowerC) return NEAR_PROXIMITY_CHAR; // Not an exact nor an accent-alike match: search the list of close keys int j = 1; - while (j < MAX_PROXIMITY_CHARS_SIZE && currentChars[j] > 0) { + while (j < MAX_PROXIMITY_CHARS_SIZE + && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c); if (matched) { if (proximityIndex) { @@ -260,6 +381,21 @@ ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(const int inde } ++j; } + if (j < MAX_PROXIMITY_CHARS_SIZE + && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + ++j; + while (j < MAX_PROXIMITY_CHARS_SIZE + && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c); + if (matched) { + if (proximityIndex) { + *proximityIndex = j; + } + return ADDITIONAL_PROXIMITY_CHAR; + } + ++j; + } + } // Was not included, signal this as an unrelated character. return UNRELATED_CHAR; diff --git a/native/src/proximity_info.h b/native/src/proximity_info.h index 35e354c6e..1a47aff84 100644 --- a/native/src/proximity_info.h +++ b/native/src/proximity_info.h @@ -18,6 +18,7 @@ #define LATINIME_PROXIMITY_INFO_H #include <stdint.h> +#include <string> #include "defines.h" @@ -26,7 +27,7 @@ namespace latinime { class Correction; class ProximityInfo { -public: + public: static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10; static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR = 1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2; @@ -38,25 +39,28 @@ public: // It is a char located nearby on the keyboard NEAR_PROXIMITY_CHAR, // It is an unrelated char - UNRELATED_CHAR + UNRELATED_CHAR, + // Additional proximity char which can differ by language. + ADDITIONAL_PROXIMITY_CHAR } ProximityType; - ProximityInfo(const int maxProximityCharsSize, const int keyboardWidth, - const int keybaordHeight, const int gridWidth, const int gridHeight, - const uint32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates, + ProximityInfo(const std::string localeStr, const int maxProximityCharsSize, + const int keyboardWidth, const int keybaordHeight, const int gridWidth, + const int gridHeight, const int mostCommonkeyWidth, + const int32_t *proximityCharsArray, const int keyCount, const int32_t *keyXCoordinates, const int32_t *keyYCoordinates, const int32_t *keyWidths, const int32_t *keyHeights, const int32_t *keyCharCodes, const float *sweetSpotCenterXs, const float *sweetSpotCenterYs, const float *sweetSpotRadii); ~ProximityInfo(); bool hasSpaceProximity(const int x, const int y) const; - void setInputParams(const int* inputCodes, const int inputLength, + void setInputParams(const int *inputCodes, const int inputLength, const int *xCoordinates, const int *yCoordinates); const int* getProximityCharsAt(const int index) const; unsigned short getPrimaryCharAt(const int index) const; bool existsCharInProximityAt(const int index, const int c) const; bool existsAdjacentProximityChars(const int index) const; ProximityType getMatchedProximityId(const int index, const unsigned short c, - const bool checkProximityChars, int *proximityIndex = NULL) const; + const bool checkProximityChars, int *proximityIndex = 0) const; int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const { return mNormalizedSquaredDistances[inputIndex * MAX_PROXIMITY_CHARS_SIZE + proximityIndex]; } @@ -68,7 +72,7 @@ public: return mTouchPositionCorrectionEnabled; } -private: + private: // The max number of the keys in one keyboard layout static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64; // The upper limit of the char code in mCodeToKeyIndex @@ -85,21 +89,27 @@ private: // the radius of the key is assigned to zero. return mSweetSpotRadii[keyIndex] > 0.0; } + bool isOnKey(const int keyId, const int x, const int y); + int squaredDistanceToEdge(const int keyId, const int x, const int y); + void calculateNearbyKeyCodes( + const int x, const int y, const int32_t primaryKey, int *inputCodes); const int MAX_PROXIMITY_CHARS_SIZE; const int KEYBOARD_WIDTH; const int KEYBOARD_HEIGHT; const int GRID_WIDTH; const int GRID_HEIGHT; + const int MOST_COMMON_KEY_WIDTH_SQUARE; const int CELL_WIDTH; const int CELL_HEIGHT; const int KEY_COUNT; const bool HAS_TOUCH_POSITION_CORRECTION_DATA; + const std::string mLocaleStr; const int *mInputCodes; const int *mInputXCoordinates; const int *mInputYCoordinates; bool mTouchPositionCorrectionEnabled; - uint32_t *mProximityCharsArray; + int32_t *mProximityCharsArray; int *mNormalizedSquaredDistances; int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD]; diff --git a/native/src/terminal_attributes.h b/native/src/terminal_attributes.h new file mode 100644 index 000000000..1f9815936 --- /dev/null +++ b/native/src/terminal_attributes.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#ifndef LATINIME_TERMINAL_ATTRIBUTES_H +#define LATINIME_TERMINAL_ATTRIBUTES_H + +#include "unigram_dictionary.h" + +namespace latinime { + +/** + * This class encapsulates information about a terminal that allows to + * retrieve local node attributes like the list of shortcuts without + * exposing the format structure to the client. + */ +class TerminalAttributes { + public: + class ShortcutIterator { + const uint8_t* const mDict; + bool mHasNextShortcutTarget; + int mPos; + + public: + ShortcutIterator(const uint8_t* dict, const int pos, const uint8_t flags) : mDict(dict), + mPos(pos) { + mHasNextShortcutTarget = (0 != (flags & UnigramDictionary::FLAG_HAS_SHORTCUT_TARGETS)); + } + + inline bool hasNextShortcutTarget() const { + return mHasNextShortcutTarget; + } + + // Gets the shortcut target itself as a uint16_t string. For parameters and return value + // see BinaryFormat::getWordAtAddress. + inline int getNextShortcutTarget(const int maxDepth, uint16_t* outWord) { + const int shortcutFlags = BinaryFormat::getFlagsAndForwardPointer(mDict, &mPos); + mHasNextShortcutTarget = + 0 != (shortcutFlags & UnigramDictionary::FLAG_ATTRIBUTE_HAS_NEXT); + int shortcutAddress = + BinaryFormat::getAttributeAddressAndForwardPointer(mDict, shortcutFlags, &mPos); + return BinaryFormat::getWordAtAddress(mDict, shortcutAddress, maxDepth, outWord); + } + }; + + private: + const uint8_t* const mDict; + const uint8_t mFlags; + const int mStartPos; + + public: + TerminalAttributes(const uint8_t* const dict, const uint8_t flags, const int pos) : + mDict(dict), mFlags(flags), mStartPos(pos) { + } + + inline bool isShortcutOnly() const { + return 0 != (mFlags & UnigramDictionary::FLAG_IS_SHORTCUT_ONLY); + } + + inline ShortcutIterator getShortcutIterator() const { + return ShortcutIterator(mDict, mStartPos, mFlags); + } +}; +} // namespace latinime + +#endif // LATINIME_TERMINAL_ATTRIBUTES_H diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp index 8eb5a9700..6c2c89231 100644 --- a/native/src/unigram_dictionary.cpp +++ b/native/src/unigram_dictionary.cpp @@ -25,6 +25,7 @@ #include "unigram_dictionary.h" #include "binary_format.h" +#include "terminal_attributes.h" namespace latinime { @@ -37,8 +38,7 @@ const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] = UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion) - : DICT_ROOT(streamStart + NEW_DICTIONARY_HEADER_SIZE), - MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), + : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), MAX_PROXIMITY_CHARS(maxProximityChars), IS_LATEST_DICT_VERSION(isLatestDictVersion), TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), // TODO : remove this variable. @@ -46,21 +46,25 @@ UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typed BYTES_IN_ONE_CHAR(MAX_PROXIMITY_CHARS * sizeof(int)), MAX_UMLAUT_SEARCH_DEPTH(DEFAULT_MAX_UMLAUT_SEARCH_DEPTH) { if (DEBUG_DICT) { - LOGI("UnigramDictionary - constructor"); + AKLOGI("UnigramDictionary - constructor"); } - mCorrection = new Correction(typedLetterMultiplier, fullWordMultiplier); } UnigramDictionary::~UnigramDictionary() { - delete mCorrection; } -static inline unsigned int getCodesBufferSize(const int* codes, const int codesSize, +static inline unsigned int getCodesBufferSize(const int *codes, const int codesSize, const int MAX_PROXIMITY_CHARS) { return sizeof(*codes) * MAX_PROXIMITY_CHARS * codesSize; } -bool UnigramDictionary::isDigraph(const int* codes, const int i, const int codesSize) const { +// TODO: This needs to take a const unsigned short* and not tinker with its contents +static inline void addWord( + unsigned short *word, int length, int frequency, WordsPriorityQueue *queue) { + queue->push(frequency, word, length); +} + +bool UnigramDictionary::isDigraph(const int *codes, const int i, const int codesSize) const { // There can't be a digraph if we don't have at least 2 characters to examine if (i + 2 > codesSize) return false; @@ -86,12 +90,17 @@ bool UnigramDictionary::isDigraph(const int* codes, const int i, const int codes // codesSrc is the current point in the user-input, original, content-unmodified buffer. // codesRemain is the remaining size in codesSrc. void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo, - const int *xcoordinates, const int* ycoordinates, const int *codesBuffer, - const int codesBufferSize, const int flags, const int* codesSrc, const int codesRemain, - const int currentDepth, int* codesDest, unsigned short* outWords, int* frequencies) { + const int *xcoordinates, const int *ycoordinates, const int *codesBuffer, + int *xCoordinatesBuffer, int *yCoordinatesBuffer, + const int codesBufferSize, const int flags, const int *codesSrc, + const int codesRemain, const int currentDepth, int *codesDest, Correction *correction, + WordsPriorityQueuePool *queuePool) { + const int startIndex = (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS; if (currentDepth < MAX_UMLAUT_SEARCH_DEPTH) { for (int i = 0; i < codesRemain; ++i) { + xCoordinatesBuffer[startIndex + i] = xcoordinates[codesBufferSize - codesRemain + i]; + yCoordinatesBuffer[startIndex + i] = ycoordinates[codesBufferSize - codesRemain + i]; if (isDigraph(codesSrc, i, codesRemain)) { // Found a digraph. We will try both spellings. eg. the word is "pruefen" @@ -103,10 +112,10 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit ++i; memcpy(codesDest, codesSrc, i * BYTES_IN_ONE_CHAR); getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, - codesBuffer, codesBufferSize, flags, + codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, flags, codesSrc + (i + 1) * MAX_PROXIMITY_CHARS, codesRemain - i - 1, - currentDepth + 1, codesDest + i * MAX_PROXIMITY_CHARS, outWords, - frequencies); + currentDepth + 1, codesDest + i * MAX_PROXIMITY_CHARS, correction, + queuePool); // Copy the second char of the digraph in place, then continue processing on // the remaining part of the word. @@ -114,9 +123,9 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit memcpy(codesDest + i * MAX_PROXIMITY_CHARS, codesSrc + i * MAX_PROXIMITY_CHARS, BYTES_IN_ONE_CHAR); getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, - codesBuffer, codesBufferSize, flags, codesSrc + i * MAX_PROXIMITY_CHARS, - codesRemain - i, currentDepth + 1, codesDest + i * MAX_PROXIMITY_CHARS, - outWords, frequencies); + codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, flags, + codesSrc + i * MAX_PROXIMITY_CHARS, codesRemain - i, currentDepth + 1, + codesDest + i * MAX_PROXIMITY_CHARS, correction, queuePool); return; } } @@ -128,45 +137,60 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit // eg. if the word is "ueberpruefen" we'll test, in order, against // "uberprufen", "uberpruefen", "ueberprufen", "ueberpruefen". const unsigned int remainingBytes = BYTES_IN_ONE_CHAR * codesRemain; - if (0 != remainingBytes) + if (0 != remainingBytes) { memcpy(codesDest, codesSrc, remainingBytes); + memcpy(&xCoordinatesBuffer[startIndex], &xcoordinates[codesBufferSize - codesRemain], + sizeof(int) * codesRemain); + memcpy(&yCoordinatesBuffer[startIndex], &ycoordinates[codesBufferSize - codesRemain], + sizeof(int) * codesRemain); + } - getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codesBuffer, - (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies, - flags); + getWordSuggestions(proximityInfo, xCoordinatesBuffer, yCoordinatesBuffer, codesBuffer, + startIndex + codesRemain, flags, correction, + queuePool); } -int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, +int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, + WordsPriorityQueuePool *queuePool, Correction *correction, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const int flags, unsigned short *outWords, int *frequencies) { + queuePool->clearAll(); + Correction* masterCorrection = correction; if (REQUIRES_GERMAN_UMLAUT_PROCESSING & flags) { // Incrementally tune the word and try all possibilities int codesBuffer[getCodesBufferSize(codes, codesSize, MAX_PROXIMITY_CHARS)]; + int xCoordinatesBuffer[codesSize]; + int yCoordinatesBuffer[codesSize]; getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, - codesSize, flags, codes, codesSize, 0, codesBuffer, outWords, frequencies); + xCoordinatesBuffer, yCoordinatesBuffer, + codesSize, flags, codes, codesSize, 0, codesBuffer, masterCorrection, queuePool); } else { // Normal processing - getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, - outWords, frequencies, flags); + getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, flags, + masterCorrection, queuePool); } PROF_START(20); - // Get the word count - int suggestedWordsCount = 0; - while (suggestedWordsCount < MAX_WORDS && mFrequencies[suggestedWordsCount] > 0) { - suggestedWordsCount++; + if (DEBUG_DICT) { + double ns = queuePool->getMasterQueue()->getHighestNormalizedScore( + proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0); + ns += 0; + AKLOGI("Max normalized score = %f", ns); } + const int suggestedWordsCount = + queuePool->getMasterQueue()->outputSuggestions(frequencies, outWords); if (DEBUG_DICT) { - LOGI("Returning %d words", suggestedWordsCount); + double ns = queuePool->getMasterQueue()->getHighestNormalizedScore( + proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0); + ns += 0; + AKLOGI("Returning %d words", suggestedWordsCount); /// Print the returned words for (int j = 0; j < suggestedWordsCount; ++j) { -#ifdef FLAG_DBG - short unsigned int* w = mOutputChars + j * MAX_WORD_LENGTH; + short unsigned int* w = outWords + j * MAX_WORD_LENGTH; char s[MAX_WORD_LENGTH]; for (int i = 0; i <= MAX_WORD_LENGTH; i++) s[i] = w[i]; - LOGI("%s %i", s, mFrequencies[j]); -#endif + AKLOGI("%s %i", s, frequencies[j]); } } PROF_END(20); @@ -175,23 +199,18 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x } void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, - const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, - unsigned short *outWords, int *frequencies, const int flags) { + const int *xcoordinates, const int *ycoordinates, const int *codes, + const int inputLength, const int flags, Correction *correction, + WordsPriorityQueuePool *queuePool) { PROF_OPEN; PROF_START(0); - initSuggestions( - proximityInfo, xcoordinates, ycoordinates, codes, codesSize, outWords, frequencies); - if (DEBUG_DICT) assert(codesSize == mInputLength); - - const int maxDepth = min(mInputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH); - mCorrection->initCorrection(mProximityInfo, mInputLength, maxDepth); PROF_END(0); - const bool useFullEditDistance = USE_FULL_EDIT_DISTANCE & flags; - // TODO: remove PROF_START(1); - getSuggestionCandidates(useFullEditDistance); + const bool useFullEditDistance = USE_FULL_EDIT_DISTANCE & flags; + getOneWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, useFullEditDistance, + inputLength, correction, queuePool); PROF_END(1); PROF_START(2); @@ -203,250 +222,369 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, PROF_END(3); PROF_START(4); - // Note: This line is intentionally left blank + bool hasAutoCorrectionCandidate = false; + WordsPriorityQueue* masterQueue = queuePool->getMasterQueue(); + if (masterQueue->size() > 0) { + double nsForMaster = masterQueue->getHighestNormalizedScore( + proximityInfo->getPrimaryInputWord(), inputLength, 0, 0, 0); + hasAutoCorrectionCandidate = (nsForMaster > START_TWO_WORDS_CORRECTION_THRESHOLD); + } PROF_END(4); PROF_START(5); - // Suggestions with missing space - if (SUGGEST_WORDS_WITH_MISSING_SPACE_CHARACTER - && mInputLength >= MIN_USER_TYPED_LENGTH_FOR_MISSING_SPACE_SUGGESTION) { - for (int i = 1; i < codesSize; ++i) { - if (DEBUG_DICT) { - LOGI("--- Suggest missing space characters %d", i); - } - getMissingSpaceWords(mInputLength, i, mCorrection, useFullEditDistance); - } + // Multiple word suggestions + if (SUGGEST_MULTIPLE_WORDS + && inputLength >= MIN_USER_TYPED_LENGTH_FOR_MULTIPLE_WORD_SUGGESTION) { + getSplitMultipleWordsSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, inputLength, correction, queuePool, + hasAutoCorrectionCandidate); } PROF_END(5); PROF_START(6); - if (SUGGEST_WORDS_WITH_SPACE_PROXIMITY && proximityInfo) { - // The first and last "mistyped spaces" are taken care of by excessive character handling - for (int i = 1; i < codesSize - 1; ++i) { - if (DEBUG_DICT) { - LOGI("--- Suggest words with proximity space %d", i); - } - const int x = xcoordinates[i]; - const int y = ycoordinates[i]; - if (DEBUG_PROXIMITY_INFO) { - LOGI("Input[%d] x = %d, y = %d, has space proximity = %d", - i, x, y, proximityInfo->hasSpaceProximity(x, y)); - } - if (proximityInfo->hasSpaceProximity(x, y)) { - getMistypedSpaceWords(mInputLength, i, mCorrection, useFullEditDistance); + // Note: This line is intentionally left blank + PROF_END(6); + + if (DEBUG_DICT) { + queuePool->dumpSubQueue1TopSuggestions(); + for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) { + WordsPriorityQueue* queue = queuePool->getSubQueue(FIRST_WORD_INDEX, i); + if (queue->size() > 0) { + WordsPriorityQueue::SuggestedWord* sw = queue->top(); + const int score = sw->mScore; + const unsigned short* word = sw->mWord; + const int wordLength = sw->mWordLength; + double ns = Correction::RankingAlgorithm::calcNormalizedScore( + proximityInfo->getPrimaryInputWord(), i, word, wordLength, score); + ns += 0; + AKLOGI("--- TOP SUB WORDS for %d --- %d %f [%d]", i, score, ns, + (ns > TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD)); + DUMP_WORD(proximityInfo->getPrimaryInputWord(), i); + DUMP_WORD(word, wordLength); } } } - PROF_END(6); } void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xCoordinates, - const int *yCoordinates, const int *codes, const int codesSize, - unsigned short *outWords, int *frequencies) { + const int *yCoordinates, const int *codes, const int inputLength, Correction *correction) { if (DEBUG_DICT) { - LOGI("initSuggest"); - } - mFrequencies = frequencies; - mOutputChars = outWords; - mInputLength = codesSize; - proximityInfo->setInputParams(codes, codesSize, xCoordinates, yCoordinates); - mProximityInfo = proximityInfo; -} - -static inline void registerNextLetter(unsigned short c, int *nextLetters, int nextLettersSize) { - if (c < nextLettersSize) { - nextLetters[c]++; - } -} - -// TODO: We need to optimize addWord by using STL or something -// TODO: This needs to take an const unsigned short* and not tinker with its contents -bool UnigramDictionary::addWord(unsigned short *word, int length, int frequency) { - word[length] = 0; - if (DEBUG_DICT && DEBUG_SHOW_FOUND_WORD) { -#ifdef FLAG_DBG - char s[length + 1]; - for (int i = 0; i <= length; i++) s[i] = word[i]; - LOGI("Found word = %s, freq = %d", s, frequency); -#endif - } - if (length > MAX_WORD_LENGTH) { - if (DEBUG_DICT) { - LOGI("Exceeded max word length."); - } - return false; + AKLOGI("initSuggest"); } - - // Find the right insertion point - int insertAt = 0; - while (insertAt < MAX_WORDS) { - // TODO: How should we sort words with the same frequency? - if (frequency > mFrequencies[insertAt]) { - break; - } - insertAt++; - } - if (insertAt < MAX_WORDS) { - if (DEBUG_DICT) { -#ifdef FLAG_DBG - char s[length + 1]; - for (int i = 0; i <= length; i++) s[i] = word[i]; - LOGI("Added word = %s, freq = %d, %d", s, frequency, S_INT_MAX); -#endif - } - memmove((char*) mFrequencies + (insertAt + 1) * sizeof(mFrequencies[0]), - (char*) mFrequencies + insertAt * sizeof(mFrequencies[0]), - (MAX_WORDS - insertAt - 1) * sizeof(mFrequencies[0])); - mFrequencies[insertAt] = frequency; - memmove((char*) mOutputChars + (insertAt + 1) * MAX_WORD_LENGTH * sizeof(short), - (char*) mOutputChars + insertAt * MAX_WORD_LENGTH * sizeof(short), - (MAX_WORDS - insertAt - 1) * sizeof(short) * MAX_WORD_LENGTH); - unsigned short *dest = mOutputChars + insertAt * MAX_WORD_LENGTH; - while (length--) { - *dest++ = *word++; - } - *dest = 0; // NULL terminate - if (DEBUG_DICT) { - LOGI("Added word at %d", insertAt); - } - return true; - } - return false; + proximityInfo->setInputParams(codes, inputLength, xCoordinates, yCoordinates); + const int maxDepth = min(inputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH); + correction->initCorrection(proximityInfo, inputLength, maxDepth); } static const char QUOTE = '\''; static const char SPACE = ' '; -void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance) { +void UnigramDictionary::getOneWordSuggestions(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const bool useFullEditDistance, const int inputLength, Correction *correction, + WordsPriorityQueuePool *queuePool) { + initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, inputLength, correction); + getSuggestionCandidates(useFullEditDistance, inputLength, correction, queuePool, + true /* doAutoCompletion */, DEFAULT_MAX_ERRORS, FIRST_WORD_INDEX); +} + +void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance, + const int inputLength, Correction *correction, WordsPriorityQueuePool *queuePool, + const bool doAutoCompletion, const int maxErrors, const int currentWordIndex) { // TODO: Remove setCorrectionParams - mCorrection->setCorrectionParams(0, 0, 0, - -1 /* spaceProximityPos */, -1 /* missingSpacePos */, useFullEditDistance); + correction->setCorrectionParams(0, 0, 0, + -1 /* spaceProximityPos */, -1 /* missingSpacePos */, useFullEditDistance, + doAutoCompletion, maxErrors); int rootPosition = ROOT_POS; // Get the number of children of root, then increment the position - int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition); + int childCount = BinaryFormat::getGroupCountAndForwardPointer(DICT_ROOT, &rootPosition); int outputIndex = 0; - mCorrection->initCorrectionState(rootPosition, childCount, (mInputLength <= 0)); + correction->initCorrectionState(rootPosition, childCount, (inputLength <= 0)); // Depth first search while (outputIndex >= 0) { - if (mCorrection->initProcessState(outputIndex)) { - int siblingPos = mCorrection->getTreeSiblingPos(outputIndex); + if (correction->initProcessState(outputIndex)) { + int siblingPos = correction->getTreeSiblingPos(outputIndex); int firstChildPos; const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, - mCorrection, &childCount, &firstChildPos, &siblingPos); + correction, &childCount, &firstChildPos, &siblingPos, queuePool, + currentWordIndex); // Update next sibling pos - mCorrection->setTreeSiblingPos(outputIndex, siblingPos); + correction->setTreeSiblingPos(outputIndex, siblingPos); if (needsToTraverseChildrenNodes) { // Goes to child node - outputIndex = mCorrection->goDownTree(outputIndex, childCount, firstChildPos); + outputIndex = correction->goDownTree(outputIndex, childCount, firstChildPos); } } else { // Goes to parent sibling node - outputIndex = mCorrection->getTreeParentIndex(outputIndex); + outputIndex = correction->getTreeParentIndex(outputIndex); } } } -void UnigramDictionary::getMissingSpaceWords( - const int inputLength, const int missingSpacePos, Correction *correction, - const bool useFullEditDistance) { - correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */, - -1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos, - useFullEditDistance); - getSplitTwoWordsSuggestion(inputLength, correction); -} - -void UnigramDictionary::getMistypedSpaceWords( - const int inputLength, const int spaceProximityPos, Correction *correction, - const bool useFullEditDistance) { - correction->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */, - -1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */, - useFullEditDistance); - getSplitTwoWordsSuggestion(inputLength, correction); -} - -inline bool UnigramDictionary::needsToSkipCurrentNode(const unsigned short c, - const int inputIndex, const int skipPos, const int depth) { - const unsigned short userTypedChar = mProximityInfo->getPrimaryCharAt(inputIndex); - // Skip the ' or other letter and continue deeper - return (c == QUOTE && userTypedChar != QUOTE) || skipPos == depth; -} +inline void UnigramDictionary::onTerminal(const int freq, + const TerminalAttributes& terminalAttributes, Correction *correction, + WordsPriorityQueuePool *queuePool, const bool addToMasterQueue, + const int currentWordIndex) { + const int inputIndex = correction->getInputIndex(); + const bool addToSubQueue = inputIndex < SUB_QUEUE_MAX_COUNT; -inline void UnigramDictionary::onTerminal(const int freq, Correction *correction) { int wordLength; unsigned short* wordPointer; - const int finalFreq = correction->getFinalFreq(freq, &wordPointer, &wordLength); - if (finalFreq >= 0) { - addWord(wordPointer, wordLength, finalFreq); + + if ((currentWordIndex == FIRST_WORD_INDEX) && addToMasterQueue) { + WordsPriorityQueue *masterQueue = queuePool->getMasterQueue(); + const int finalFreq = correction->getFinalFreq(freq, &wordPointer, &wordLength); + if (finalFreq != NOT_A_FREQUENCY) { + if (!terminalAttributes.isShortcutOnly()) { + addWord(wordPointer, wordLength, finalFreq, masterQueue); + } + + // Please note that the shortcut candidates will be added to the master queue only. + TerminalAttributes::ShortcutIterator iterator = + terminalAttributes.getShortcutIterator(); + while (iterator.hasNextShortcutTarget()) { + // TODO: addWord only supports weak ordering, meaning we have no means + // to control the order of the shortcuts relative to one another or to the word. + // We need to either modulate the frequency of each shortcut according + // to its own shortcut frequency or to make the queue + // so that the insert order is protected inside the queue for words + // with the same score. + uint16_t shortcutTarget[MAX_WORD_LENGTH_INTERNAL]; + const int shortcutTargetStringLength = iterator.getNextShortcutTarget( + MAX_WORD_LENGTH_INTERNAL, shortcutTarget); + addWord(shortcutTarget, shortcutTargetStringLength, finalFreq, masterQueue); + } + } + } + + // We only allow two words + other error correction for words with SUB_QUEUE_MIN_WORD_LENGTH + // or more length. + if (inputIndex >= SUB_QUEUE_MIN_WORD_LENGTH && addToSubQueue) { + WordsPriorityQueue *subQueue; + subQueue = queuePool->getSubQueue(currentWordIndex, inputIndex); + if (!subQueue) { + return; + } + const int finalFreq = correction->getFinalFreqForSubQueue(freq, &wordPointer, &wordLength, + inputIndex); + addWord(wordPointer, wordLength, finalFreq, subQueue); } } -void UnigramDictionary::getSplitTwoWordsSuggestion( - const int inputLength, Correction* correction) { - const int spaceProximityPos = correction->getSpaceProximityPos(); - const int missingSpacePos = correction->getMissingSpacePos(); +bool UnigramDictionary::getSubStringSuggestion( + ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, + const int *codes, const bool useFullEditDistance, Correction *correction, + WordsPriorityQueuePool* queuePool, const int inputLength, + const bool hasAutoCorrectionCandidate, const int currentWordIndex, + const int inputWordStartPos, const int inputWordLength, + const int outputWordStartPos, const bool isSpaceProximity, int *freqArray, + int*wordLengthArray, unsigned short* outputWord, int *outputWordLength) { + unsigned short* tempOutputWord = 0; + int nextWordLength = 0; + // TODO: Optimize init suggestion + initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, + inputLength, correction); + + int freq = getMostFrequentWordLike( + inputWordStartPos, inputWordLength, proximityInfo, mWord); + if (freq > 0) { + nextWordLength = inputWordLength; + tempOutputWord = mWord; + } else if (!hasAutoCorrectionCandidate) { + if (inputWordStartPos > 0) { + const int offset = inputWordStartPos; + initSuggestions(proximityInfo, &xcoordinates[offset], &ycoordinates[offset], + codes + offset * MAX_PROXIMITY_CHARS, inputWordLength, correction); + queuePool->clearSubQueue(currentWordIndex); + getSuggestionCandidates(useFullEditDistance, inputWordLength, correction, + queuePool, false, MAX_ERRORS_FOR_TWO_WORDS, currentWordIndex); + if (DEBUG_DICT) { + if (currentWordIndex < MULTIPLE_WORDS_SUGGESTION_MAX_WORDS) { + AKLOGI("Dump word candidates(%d) %d", currentWordIndex, inputWordLength); + for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) { + queuePool->getSubQueue(currentWordIndex, i)->dumpTopWord(); + } + } + } + } + WordsPriorityQueue* queue = queuePool->getSubQueue(currentWordIndex, inputWordLength); + if (!queue || queue->size() < 1) { + return false; + } + int score = 0; + const double ns = queue->getHighestNormalizedScore( + proximityInfo->getPrimaryInputWord(), inputWordLength, + &tempOutputWord, &score, &nextWordLength); + if (DEBUG_DICT) { + AKLOGI("NS(%d) = %f, Score = %d", currentWordIndex, ns, score); + } + // Two words correction won't be done if the score of the first word doesn't exceed the + // threshold. + if (ns < TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD + || nextWordLength < SUB_QUEUE_MIN_WORD_LENGTH) { + return false; + } + freq = score >> (nextWordLength + TWO_WORDS_PLUS_OTHER_ERROR_CORRECTION_DEMOTION_DIVIDER); + } if (DEBUG_DICT) { - int inputCount = 0; - if (spaceProximityPos >= 0) ++inputCount; - if (missingSpacePos >= 0) ++inputCount; - assert(inputCount <= 1); - } - const bool isSpaceProximity = spaceProximityPos >= 0; - const int firstWordStartPos = 0; - const int secondWordStartPos = isSpaceProximity ? (spaceProximityPos + 1) : missingSpacePos; - const int firstWordLength = isSpaceProximity ? spaceProximityPos : missingSpacePos; - const int secondWordLength = isSpaceProximity - ? (inputLength - spaceProximityPos - 1) - : (inputLength - missingSpacePos); - - if (inputLength >= MAX_WORD_LENGTH) return; - if (0 >= firstWordLength || 0 >= secondWordLength || firstWordStartPos >= secondWordStartPos - || firstWordStartPos < 0 || secondWordStartPos + secondWordLength > inputLength) - return; + AKLOGI("Freq(%d): %d, length: %d, input length: %d, input start: %d (%d)" + , currentWordIndex, freq, nextWordLength, inputWordLength, inputWordStartPos, + wordLengthArray[0]); + } + if (freq <= 0 || nextWordLength <= 0 + || MAX_WORD_LENGTH <= (outputWordStartPos + nextWordLength)) { + return false; + } + for (int i = 0; i < nextWordLength; ++i) { + outputWord[outputWordStartPos + i] = tempOutputWord[i]; + } - const int newWordLength = firstWordLength + secondWordLength + 1; - // Allocating variable length array on stack - unsigned short word[newWordLength]; - const int firstFreq = getMostFrequentWordLike(firstWordStartPos, firstWordLength, mWord); - if (DEBUG_DICT) { - LOGI("First freq: %d", firstFreq); + // Put output values + freqArray[currentWordIndex] = freq; + // TODO: put output length instead of input length + wordLengthArray[currentWordIndex] = inputWordLength; + const int tempOutputWordLength = outputWordStartPos + nextWordLength; + if (outputWordLength) { + *outputWordLength = tempOutputWordLength; } - if (firstFreq <= 0) return; - for (int i = 0; i < firstWordLength; ++i) { - word[i] = mWord[i]; + if ((inputWordStartPos + inputWordLength) < inputLength) { + if (outputWordStartPos + nextWordLength >= MAX_WORD_LENGTH) { + return false; + } + outputWord[tempOutputWordLength] = SPACE; + if (outputWordLength) { + ++*outputWordLength; + } + } else if (currentWordIndex >= 1) { + // TODO: Handle 3 or more words + const int pairFreq = correction->getFreqForSplitMultipleWords( + freqArray, wordLengthArray, currentWordIndex + 1, isSpaceProximity, outputWord); + if (DEBUG_DICT) { + DUMP_WORD(outputWord, tempOutputWordLength); + AKLOGI("Split two words: %d, %d, %d, %d, (%d) %d", freqArray[0], freqArray[1], pairFreq, + inputLength, wordLengthArray[0], tempOutputWordLength); + } + addWord(outputWord, tempOutputWordLength, pairFreq, queuePool->getMasterQueue()); } + return true; +} - const int secondFreq = getMostFrequentWordLike(secondWordStartPos, secondWordLength, mWord); - if (DEBUG_DICT) { - LOGI("Second freq: %d", secondFreq); +void UnigramDictionary::getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const bool useFullEditDistance, const int inputLength, + Correction *correction, WordsPriorityQueuePool* queuePool, + const bool hasAutoCorrectionCandidate, const int startInputPos, const int startWordIndex, + const int outputWordLength, int *freqArray, int* wordLengthArray, + unsigned short* outputWord) { + if (startWordIndex >= (MULTIPLE_WORDS_SUGGESTION_MAX_WORDS - 1)) { + // Return if the last word index + return; } - if (secondFreq <= 0) return; + if (startWordIndex >= 1 + && (hasAutoCorrectionCandidate + || inputLength < MIN_INPUT_LENGTH_FOR_THREE_OR_MORE_WORDS_CORRECTION)) { + // Do not suggest 3+ words if already has auto correction candidate + return; + } + for (int i = startInputPos + 1; i < inputLength; ++i) { + if (DEBUG_CORRECTION_FREQ) { + AKLOGI("Multi words(%d), start in %d sep %d start out %d", + startWordIndex, startInputPos, i, outputWordLength); + DUMP_WORD(outputWord, outputWordLength); + } + int tempOutputWordLength = 0; + // Current word + int inputWordStartPos = startInputPos; + int inputWordLength = i - startInputPos; + if (!getSubStringSuggestion(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, correction, queuePool, inputLength, hasAutoCorrectionCandidate, + startWordIndex, inputWordStartPos, inputWordLength, outputWordLength, + true /* not used */, freqArray, wordLengthArray, outputWord, + &tempOutputWordLength)) { + continue; + } + + if (DEBUG_CORRECTION_FREQ) { + AKLOGI("Do missing space correction"); + } + // Next word + // Missing space + inputWordStartPos = i; + inputWordLength = inputLength - i; + if(!getSubStringSuggestion(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, correction, queuePool, inputLength, hasAutoCorrectionCandidate, + startWordIndex + 1, inputWordStartPos, inputWordLength, tempOutputWordLength, + false /* missing space */, freqArray, wordLengthArray, outputWord, 0)) { + getMultiWordsSuggestionRec(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, inputLength, correction, queuePool, + hasAutoCorrectionCandidate, inputWordStartPos, startWordIndex + 1, + tempOutputWordLength, freqArray, wordLengthArray, outputWord); + } - word[firstWordLength] = SPACE; - for (int i = (firstWordLength + 1); i < newWordLength; ++i) { - word[i] = mWord[i - firstWordLength - 1]; + // Mistyped space + ++inputWordStartPos; + --inputWordLength; + + if (inputWordLength <= 0) { + continue; + } + + const int x = xcoordinates[inputWordStartPos - 1]; + const int y = ycoordinates[inputWordStartPos - 1]; + if (!proximityInfo->hasSpaceProximity(x, y)) { + continue; + } + + if (DEBUG_CORRECTION_FREQ) { + AKLOGI("Do mistyped space correction"); + } + getSubStringSuggestion(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, correction, queuePool, inputLength, hasAutoCorrectionCandidate, + startWordIndex + 1, inputWordStartPos, inputWordLength, tempOutputWordLength, + true /* mistyped space */, freqArray, wordLengthArray, outputWord, 0); } +} - const int pairFreq = mCorrection->getFreqForSplitTwoWords(firstFreq, secondFreq, word); +void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const bool useFullEditDistance, const int inputLength, + Correction *correction, WordsPriorityQueuePool* queuePool, + const bool hasAutoCorrectionCandidate) { + if (inputLength >= MAX_WORD_LENGTH) return; + if (DEBUG_DICT) { + // MAX_PROXIMITY_CHARS_SIZE in ProximityInfo.java should be 16 + assert(MAX_PROXIMITY_CHARS == 16); + } if (DEBUG_DICT) { - LOGI("Split two words: %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength); + AKLOGI("--- Suggest multiple words"); } - addWord(word, newWordLength, pairFreq); - return; + + // Allocating fixed length array on stack + unsigned short outputWord[MAX_WORD_LENGTH]; + int freqArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; + int wordLengthArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; + const int outputWordLength = 0; + const int startInputPos = 0; + const int startWordIndex = 0; + getMultiWordsSuggestionRec(proximityInfo, xcoordinates, ycoordinates, codes, + useFullEditDistance, inputLength, correction, queuePool, hasAutoCorrectionCandidate, + startInputPos, startWordIndex, outputWordLength, freqArray, wordLengthArray, + outputWord); } // Wrapper for getMostFrequentWordLikeInner, which matches it to the previous // interface. inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, - const int inputLength, unsigned short *word) { + const int inputLength, ProximityInfo *proximityInfo, unsigned short *word) { uint16_t inWord[inputLength]; for (int i = 0; i < inputLength; ++i) { - inWord[i] = (uint16_t)mProximityInfo->getPrimaryCharAt(startInputIndex + i); + inWord[i] = (uint16_t)proximityInfo->getPrimaryCharAt(startInputIndex + i); } return getMostFrequentWordLikeInner(inWord, inputLength, word); } @@ -470,8 +608,8 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, const bool hasMultipleChars = (0 != (UnigramDictionary::FLAG_HAS_MULTIPLE_CHARS & flags)); int pos = startPos; int32_t character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); - int32_t baseChar = Dictionary::toBaseLowerCase(character); - const uint16_t wChar = Dictionary::toBaseLowerCase(inWord[startInputIndex]); + int32_t baseChar = toBaseLowerCase(character); + const uint16_t wChar = toBaseLowerCase(inWord[startInputIndex]); if (baseChar != wChar) { *outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos; @@ -483,8 +621,8 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, if (hasMultipleChars) { character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); while (NOT_A_CHARACTER != character) { - baseChar = Dictionary::toBaseLowerCase(character); - if (Dictionary::toBaseLowerCase(inWord[++inputIndex]) != baseChar) { + baseChar = toBaseLowerCase(character); + if (toBaseLowerCase(inWord[++inputIndex]) != baseChar) { *outPos = BinaryFormat::skipOtherCharacters(root, pos); *outInputIndex = startInputIndex; return false; @@ -521,9 +659,10 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWor int maxFreq = -1; const uint8_t* const root = DICT_ROOT; - mStackChildCount[0] = root[0]; + int startPos = 0; + mStackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos); mStackInputIndex[0] = 0; - mStackSiblingPos[0] = 1; + mStackSiblingPos[0] = startPos; while (depth >= 0) { const int charGroupCount = mStackChildCount[depth]; int pos = mStackSiblingPos[depth]; @@ -597,7 +736,8 @@ int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offs // given level, as output into newCount when traversing this level's parent. inline bool UnigramDictionary::processCurrentNode(const int initialPos, Correction *correction, int *newCount, - int *newChildrenPosition, int *nextSiblingPosition) { + int *newChildrenPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool, + const int currentWordIndex) { if (DEBUG_DICT) { correction->checkState(); } @@ -648,7 +788,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, if (stateType == Correction::TRAVERSE_ALL_ON_TERMINAL || stateType == Correction::ON_TERMINAL) { needsToInvokeOnTerminal = true; - } else if (stateType == Correction::UNRELATED) { + } else if (stateType == Correction::UNRELATED || correction->needsToPrune()) { // We found that this is an unrelated character, so we should give up traversing // this node and its children entirely. // However we may not be on the last virtual node yet so we skip the remaining @@ -672,12 +812,14 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, } while (NOT_A_CHARACTER != c); if (isTerminalNode) { - if (needsToInvokeOnTerminal) { - // The frequency should be here, because we come here only if this is actually - // a terminal node, and we are on its last char. - const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos); - onTerminal(freq, mCorrection); - } + // The frequency should be here, because we come here only if this is actually + // a terminal node, and we are on its last char. + const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos); + const int childrenAddressPos = BinaryFormat::skipFrequency(flags, pos); + const int attributesPos = BinaryFormat::skipChildrenPosition(flags, childrenAddressPos); + TerminalAttributes terminalAttributes(DICT_ROOT, flags, attributesPos); + onTerminal(freq, terminalAttributes, correction, queuePool, needsToInvokeOnTerminal, + currentWordIndex); // If there are more chars in this node, then this virtual node has children. // If we are on the last char, this virtual node has children if this node has. @@ -702,7 +844,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, *nextSiblingPosition = BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); if (DEBUG_DICT_FULL) { - LOGI("Traversing was pruned."); + AKLOGI("Traversing was pruned."); } return false; } diff --git a/native/src/unigram_dictionary.h b/native/src/unigram_dictionary.h index ef9709a89..12b68d71b 100644 --- a/native/src/unigram_dictionary.h +++ b/native/src/unigram_dictionary.h @@ -22,17 +22,14 @@ #include "correction_state.h" #include "defines.h" #include "proximity_info.h" - -#ifndef NULL -#define NULL 0 -#endif +#include "words_priority_queue.h" +#include "words_priority_queue_pool.h" namespace latinime { +class TerminalAttributes; class UnigramDictionary { - -public: - + public: // Mask and flags for children address type selection. static const int MASK_GROUP_ADDRESS_TYPE = 0xC0; static const int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00; @@ -46,8 +43,14 @@ public: // Flag for terminal groups static const int FLAG_IS_TERMINAL = 0x10; + // Flag for shortcut targets presence + static const int FLAG_HAS_SHORTCUT_TARGETS = 0x08; // Flag for bigram presence static const int FLAG_HAS_BIGRAMS = 0x04; + // Flag for shortcut-only words. Some words are shortcut-only, which means they match when + // the user types them but they don't pop in the suggestion strip, only the words they are + // shortcuts for do. + static const int FLAG_IS_SHORTCUT_ONLY = 0x02; // Attribute (bigram/shortcut) related flags: // Flag for presence of more attributes @@ -64,47 +67,74 @@ public: static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20; static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30; + // Error tolerances + static const int DEFAULT_MAX_ERRORS = 2; + static const int MAX_ERRORS_FOR_TWO_WORDS = 1; + UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultipler, int fullWordMultiplier, int maxWordLength, int maxWords, int maxProximityChars, const bool isLatestDictVersion); bool isValidWord(const uint16_t* const inWord, const int length) const; int getBigramPosition(int pos, unsigned short *word, int offset, int length) const; - int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, + int getSuggestions(ProximityInfo *proximityInfo, WordsPriorityQueuePool *queuePool, + Correction *correction, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const int flags, unsigned short *outWords, int *frequencies); virtual ~UnigramDictionary(); -private: - + private: void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, - const int *ycoordinates, const int *codes, const int codesSize, - unsigned short *outWords, int *frequencies, const int flags); - bool isDigraph(const int* codes, const int i, const int codesSize) const; + const int *ycoordinates, const int *codes, const int inputLength, + const int flags, Correction *correction, WordsPriorityQueuePool *queuePool); + bool isDigraph(const int *codes, const int i, const int codesSize) const; void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo, const int *xcoordinates, const int* ycoordinates, const int *codesBuffer, - const int codesBufferSize, const int flags, const int* codesSrc, const int codesRemain, - const int currentDepth, int* codesDest, unsigned short* outWords, int* frequencies); + int *xCoordinatesBuffer, int *yCoordinatesBuffer, + const int codesBufferSize, const int flags, const int* codesSrc, + const int codesRemain, const int currentDepth, int* codesDest, Correction *correction, + WordsPriorityQueuePool* queuePool); void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, - const int *ycoordinates, const int *codes, const int codesSize, - unsigned short *outWords, int *frequencies); - void getSuggestionCandidates(const bool useFullEditDistance); - bool addWord(unsigned short *word, int length, int frequency); - void getSplitTwoWordsSuggestion(const int inputLength, Correction *correction); - void getMissingSpaceWords(const int inputLength, const int missingSpacePos, - Correction *correction, const bool useFullEditDistance); - void getMistypedSpaceWords(const int inputLength, const int spaceProximityPos, - Correction *correction, const bool useFullEditDistance); - void onTerminal(const int freq, Correction *correction); + const int *ycoordinates, const int *codes, const int codesSize, Correction *correction); + void getOneWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, + const int *ycoordinates, const int *codes, const bool useFullEditDistance, + const int inputLength, Correction *correction, WordsPriorityQueuePool* queuePool); + void getSuggestionCandidates( + const bool useFullEditDistance, const int inputLength, Correction *correction, + WordsPriorityQueuePool* queuePool, const bool doAutoCompletion, const int maxErrors, + const int currentWordIndex); + void getSplitMultipleWordsSuggestions(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const bool useFullEditDistance, const int inputLength, + Correction *correction, WordsPriorityQueuePool* queuePool, + const bool hasAutoCorrectionCandidate); + void onTerminal(const int freq, const TerminalAttributes& terminalAttributes, + Correction *correction, WordsPriorityQueuePool *queuePool, const bool addToMasterQueue, + const int currentWordIndex); bool needsToSkipCurrentNode(const unsigned short c, const int inputIndex, const int skipPos, const int depth); // Process a node by considering proximity, missing and excessive character - bool processCurrentNode(const int initialPos, - Correction *correction, int *newCount, - int *newChildPosition, int *nextSiblingPosition); + bool processCurrentNode(const int initialPos, Correction *correction, int *newCount, + int *newChildPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool, + const int currentWordIndex); int getMostFrequentWordLike(const int startInputIndex, const int inputLength, - unsigned short *word); + ProximityInfo *proximityInfo, unsigned short *word); int getMostFrequentWordLikeInner(const uint16_t* const inWord, const int length, - short unsigned int* outWord); + short unsigned int *outWord); + bool getSubStringSuggestion( + ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, + const int *codes, const bool useFullEditDistance, Correction *correction, + WordsPriorityQueuePool* queuePool, const int inputLength, + const bool hasAutoCorrectionCandidate, const int currentWordIndex, + const int inputWordStartPos, const int inputWordLength, + const int outputWordStartPos, const bool isSpaceProximity, int *freqArray, + int *wordLengthArray, unsigned short* outputWord, int *outputWordLength); + void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const bool useFullEditDistance, const int inputLength, + Correction *correction, WordsPriorityQueuePool* queuePool, + const bool hasAutoCorrectionCandidate, const int startPos, const int startWordIndex, + const int outputWordLength, int *freqArray, int* wordLengthArray, + unsigned short* outputWord); const uint8_t* const DICT_ROOT; const int MAX_WORD_LENGTH; @@ -127,14 +157,8 @@ private: }; static const struct digraph_t { int first; int second; } GERMAN_UMLAUT_DIGRAPHS[]; - int *mFrequencies; - unsigned short *mOutputChars; - ProximityInfo *mProximityInfo; - Correction *mCorrection; - int mInputLength; - // MAX_WORD_LENGTH_INTERNAL must be bigger than MAX_WORD_LENGTH - unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; - + // Still bundled members + unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];// TODO: remove int mStackChildCount[MAX_WORD_LENGTH_INTERNAL];// TODO: remove int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];// TODO: remove int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];// TODO: remove diff --git a/native/src/words_priority_queue.h b/native/src/words_priority_queue.h new file mode 100644 index 000000000..249962eec --- /dev/null +++ b/native/src/words_priority_queue.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LATINIME_WORDS_PRIORITY_QUEUE_H +#define LATINIME_WORDS_PRIORITY_QUEUE_H + +#include <cstring> // for memcpy() +#include <iostream> +#include <queue> +#include "defines.h" + +namespace latinime { + +class WordsPriorityQueue { + public: + class SuggestedWord { + public: + int mScore; + unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; + int mWordLength; + bool mUsed; + + void setParams(int score, unsigned short* word, int wordLength) { + mScore = score; + mWordLength = wordLength; + memcpy(mWord, word, sizeof(unsigned short) * wordLength); + mUsed = true; + } + }; + + WordsPriorityQueue(int maxWords, int maxWordLength) : + MAX_WORDS((unsigned int) maxWords), MAX_WORD_LENGTH( + (unsigned int) maxWordLength) { + mSuggestedWords = new SuggestedWord[maxWordLength]; + for (int i = 0; i < maxWordLength; ++i) { + mSuggestedWords[i].mUsed = false; + } + mHighestSuggestedWord = 0; + } + + ~WordsPriorityQueue() { + delete[] mSuggestedWords; + } + + void push(int score, unsigned short* word, int wordLength) { + SuggestedWord* sw = 0; + if (mSuggestions.size() >= MAX_WORDS) { + sw = mSuggestions.top(); + const int minScore = sw->mScore; + if (minScore >= score) { + return; + } else { + sw->mUsed = false; + mSuggestions.pop(); + } + } + if (sw == 0) { + sw = getFreeSuggestedWord(score, word, wordLength); + } else { + sw->setParams(score, word, wordLength); + } + if (sw == 0) { + AKLOGE("SuggestedWord is accidentally null."); + return; + } + if (DEBUG_WORDS_PRIORITY_QUEUE) { + AKLOGI("Push word. %d, %d", score, wordLength); + DUMP_WORD(word, wordLength); + } + mSuggestions.push(sw); + if (!mHighestSuggestedWord || mHighestSuggestedWord->mScore < sw->mScore) { + mHighestSuggestedWord = sw; + } + } + + SuggestedWord* top() { + if (mSuggestions.empty()) return 0; + SuggestedWord* sw = mSuggestions.top(); + return sw; + } + + int outputSuggestions(int *frequencies, unsigned short *outputChars) { + mHighestSuggestedWord = 0; + const unsigned int size = min( + MAX_WORDS, static_cast<unsigned int>(mSuggestions.size())); + int index = size - 1; + while (!mSuggestions.empty() && index >= 0) { + SuggestedWord* sw = mSuggestions.top(); + if (DEBUG_WORDS_PRIORITY_QUEUE) { + AKLOGI("dump word. %d", sw->mScore); + DUMP_WORD(sw->mWord, sw->mWordLength); + } + const unsigned int wordLength = sw->mWordLength; + char* targetAdr = (char*) outputChars + + (index) * MAX_WORD_LENGTH * sizeof(short); + frequencies[index] = sw->mScore; + memcpy(targetAdr, sw->mWord, (wordLength) * sizeof(short)); + if (wordLength < MAX_WORD_LENGTH) { + ((unsigned short*) targetAdr)[wordLength] = 0; + } + sw->mUsed = false; + mSuggestions.pop(); + --index; + } + return size; + } + + int size() const { + return mSuggestions.size(); + } + + void clear() { + mHighestSuggestedWord = 0; + while (!mSuggestions.empty()) { + SuggestedWord* sw = mSuggestions.top(); + if (DEBUG_WORDS_PRIORITY_QUEUE) { + AKLOGI("Clear word. %d", sw->mScore); + DUMP_WORD(sw->mWord, sw->mWordLength); + } + sw->mUsed = false; + mSuggestions.pop(); + } + } + + void dumpTopWord() { + if (size() <= 0) { + return; + } + DUMP_WORD(mHighestSuggestedWord->mWord, mHighestSuggestedWord->mWordLength); + } + + double getHighestNormalizedScore(const unsigned short* before, const int beforeLength, + unsigned short** outWord, int *outScore, int *outLength) { + if (!mHighestSuggestedWord) { + return 0.0; + } + SuggestedWord* sw = mHighestSuggestedWord; + const int score = sw->mScore; + unsigned short* word = sw->mWord; + const int wordLength = sw->mWordLength; + if (outScore) { + *outScore = score; + } + if (outWord) { + *outWord = word; + } + if (outLength) { + *outLength = wordLength; + } + return Correction::RankingAlgorithm::calcNormalizedScore( + before, beforeLength, word, wordLength, score); + } + + private: + struct wordComparator { + bool operator ()(SuggestedWord * left, SuggestedWord * right) { + return left->mScore > right->mScore; + } + }; + + SuggestedWord* getFreeSuggestedWord(int score, unsigned short* word, + int wordLength) { + for (unsigned int i = 0; i < MAX_WORD_LENGTH; ++i) { + if (!mSuggestedWords[i].mUsed) { + mSuggestedWords[i].setParams(score, word, wordLength); + return &mSuggestedWords[i]; + } + } + return 0; + } + + typedef std::priority_queue<SuggestedWord*, std::vector<SuggestedWord*>, + wordComparator> Suggestions; + Suggestions mSuggestions; + const unsigned int MAX_WORDS; + const unsigned int MAX_WORD_LENGTH; + SuggestedWord* mSuggestedWords; + SuggestedWord* mHighestSuggestedWord; +}; +} + +#endif // LATINIME_WORDS_PRIORITY_QUEUE_H diff --git a/native/src/words_priority_queue_pool.h b/native/src/words_priority_queue_pool.h new file mode 100644 index 000000000..5b50e8f4f --- /dev/null +++ b/native/src/words_priority_queue_pool.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LATINIME_WORDS_PRIORITY_QUEUE_POOL_H +#define LATINIME_WORDS_PRIORITY_QUEUE_POOL_H + +#include <assert.h> +#include <new> +#include "words_priority_queue.h" + +namespace latinime { + +class WordsPriorityQueuePool { + public: + WordsPriorityQueuePool(int mainQueueMaxWords, int subQueueMaxWords, int maxWordLength) { + mMasterQueue = new(mMasterQueueBuf) WordsPriorityQueue(mainQueueMaxWords, maxWordLength); + for (int i = 0, subQueueBufOffset = 0; + i < MULTIPLE_WORDS_SUGGESTION_MAX_WORDS * SUB_QUEUE_MAX_COUNT; + ++i, subQueueBufOffset += sizeof(WordsPriorityQueue)) { + mSubQueues[i] = new(mSubQueueBuf + subQueueBufOffset) + WordsPriorityQueue(subQueueMaxWords, maxWordLength); + } + } + + virtual ~WordsPriorityQueuePool() { + } + + WordsPriorityQueue* getMasterQueue() { + return mMasterQueue; + } + + WordsPriorityQueue* getSubQueue(const int wordIndex, const int inputWordLength) { + if (wordIndex >= MULTIPLE_WORDS_SUGGESTION_MAX_WORDS) { + return 0; + } + if (inputWordLength < 0 || inputWordLength >= SUB_QUEUE_MAX_COUNT) { + if (DEBUG_WORDS_PRIORITY_QUEUE) { + assert(false); + } + return 0; + } + return mSubQueues[wordIndex * SUB_QUEUE_MAX_COUNT + inputWordLength]; + } + + inline void clearAll() { + mMasterQueue->clear(); + for (int i = 0; i < MULTIPLE_WORDS_SUGGESTION_MAX_WORDS; ++i) { + clearSubQueue(i); + } + } + + inline void clearSubQueue(const int wordIndex) { + for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) { + WordsPriorityQueue* queue = getSubQueue(wordIndex, i); + if (queue) { + queue->clear(); + } + } + } + + void dumpSubQueue1TopSuggestions() { + AKLOGI("DUMP SUBQUEUE1 TOP SUGGESTIONS"); + for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) { + getSubQueue(0, i)->dumpTopWord(); + } + } + + private: + WordsPriorityQueue* mMasterQueue; + WordsPriorityQueue* mSubQueues[SUB_QUEUE_MAX_COUNT * MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; + char mMasterQueueBuf[sizeof(WordsPriorityQueue)]; + char mSubQueueBuf[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS + * SUB_QUEUE_MAX_COUNT * sizeof(WordsPriorityQueue)]; +}; +} + +#endif // LATINIME_WORDS_PRIORITY_QUEUE_POOL_H diff --git a/tests/Android.mk b/tests/Android.mk index 658e8e294..6634070e9 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -1,3 +1,17 @@ +# Copyright (C) 2011 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. + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 210e81489..38a2ecfeb 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -22,8 +22,6 @@ <application> <uses-library android:name="android.test.runner" /> <!-- meta-data android:name="com.android.contacts.iconset" android:resource="@xml/iconset" /--> - <uses-permission android:name="android.permission.READ_CONTACTS" /> - </application> <instrumentation android:name="android.test.InstrumentationTestRunner" diff --git a/tests/data/bigramlist.xml b/tests/data/bigramlist.xml index dd3f2916e..d3d8bb801 100644 --- a/tests/data/bigramlist.xml +++ b/tests/data/bigramlist.xml @@ -25,7 +25,7 @@ <bi w1="about" count="3"> <w w2="part" p="117" /> <w w2="business" p="100" /> - <w w2="being" p="10" /> + <w w2="being" p="90" /> </bi> <bi w1="business" count="1"> <w w2="people" p="100" /> diff --git a/tests/res/raw/test.dict b/tests/res/raw/test.dict Binary files differdeleted file mode 100644 index 6a5d6d794..000000000 --- a/tests/res/raw/test.dict +++ /dev/null diff --git a/tests/res/values/donottranslate.xml b/tests/res/values/donottranslate.xml new file mode 100644 index 000000000..1ca4451d4 --- /dev/null +++ b/tests/res/values/donottranslate.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <string name="empty_string">""</string> + <string name="single_char">"a"</string> + <string name="space">" "</string> + <string name="single_label">"abc"</string> + <string name="spaces">" "</string> + <string name="spaces_in_label">"a b c"</string> + <string name="spaces_at_beginning_of_label">" abc"</string> + <string name="spaces_at_end_of_label">"abc "</string> + <string name="label_surrounded_by_spaces">" abc "</string> + <string name="escaped_char">"\\a"</string> + <string name="escaped_comma">"\\,"</string> + <string name="escaped_comma_escape">"a\\,\\"</string> + <string name="escaped_escape">"\\\\"</string> + <string name="escaped_label">"a\\bc"</string> + <string name="escaped_label_at_beginning">"\\abc"</string> + <string name="escaped_label_at_end">"abc\\"</string> + <string name="escaped_label_with_comma">"a\\,c"</string> + <string name="escaped_label_with_comma_at_beginning">"\\,bc"</string> + <string name="escaped_label_with_comma_at_end">"ab\\,"</string> + <string name="escaped_label_with_successive">"\\,\\\\bc"</string> + <string name="escaped_label_with_escape">"a\\\\c"</string> + <string name="multiple_chars">"a,b,c"</string> + <string name="multiple_chars_surrounded_by_spaces">" a , b , c "</string> + <string name="multiple_labels">"abc,def,ghi"</string> + <string name="multiple_labels_surrounded_by_spaces">" abc , def , ghi "</string> + <string name="multiple_chars_with_comma">"a,\\,,c"</string> + <string name="multiple_chars_with_comma_surrounded_by_spaces">" a , \\, , c "</string> + <string name="multiple_labels_with_escape">"\\abc,d\\ef,gh\\i"</string> + <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> + <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> + <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> + <string name="indirect_string">@string/multiple_chars</string> + <string name="indirect_string_with_literal">x,@string/multiple_chars,y</string> + <string name="infinite_indirection">infinite,@string/infinite_indirection,loop</string> +</resources> diff --git a/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java deleted file mode 100644 index a143bbad5..000000000 --- a/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java +++ /dev/null @@ -1,1416 +0,0 @@ -/* - * Copyright (C) 2011 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.keyboard; - -import com.android.inputmethod.keyboard.MiniKeyboard.Builder.MiniKeyboardParams; - -import android.test.AndroidTestCase; - -public class MiniKeyboardBuilderTests extends AndroidTestCase { - private static final int MAX_COLUMNS = 5; - private static final int WIDTH = 10; - private static final int HEIGHT = 10; - - private static final int KEYBOARD_WIDTH = WIDTH * 10; - private static final int XPOS_L0 = WIDTH * 0; - private static final int XPOS_L1 = WIDTH * 1; - private static final int XPOS_L2 = WIDTH * 2; - private static final int XPOS_M0 = WIDTH * 5; - private static final int XPOS_R3 = WIDTH * 6; - private static final int XPOS_R2 = WIDTH * 7; - private static final int XPOS_R1 = WIDTH * 8; - private static final int XPOS_R0 = WIDTH * 9; - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testLayoutError() { - MiniKeyboardParams params = null; - try { - params = new MiniKeyboardParams(10, MAX_COLUMNS + 1, WIDTH, HEIGHT, WIDTH * 2, - WIDTH * MAX_COLUMNS); - fail("Should throw IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // Too small keyboard to hold mini keyboard. - } - assertNull("Too small keyboard to hold mini keyboard", params); - } - - // Mini keyboard layout test. - // "[n]" represents n-th key position in mini keyboard. - // "[1]" is the default key. - - // [1] - public void testLayout1KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("1 key M0 columns", 1, params.mNumColumns); - assertEquals("1 key M0 rows", 1, params.mNumRows); - assertEquals("1 key M0 left", 0, params.mLeftKeys); - assertEquals("1 key M0 right", 1, params.mRightKeys); - assertEquals("1 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |[1] - public void testLayout1KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("1 key L0 columns", 1, params.mNumColumns); - assertEquals("1 key L0 rows", 1, params.mNumRows); - assertEquals("1 key L0 left", 0, params.mLeftKeys); - assertEquals("1 key L0 right", 1, params.mRightKeys); - assertEquals("1 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [1] - public void testLayout1KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("1 key L1 columns", 1, params.mNumColumns); - assertEquals("1 key L1 rows", 1, params.mNumRows); - assertEquals("1 key L1 left", 0, params.mLeftKeys); - assertEquals("1 key L1 right", 1, params.mRightKeys); - assertEquals("1 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [1] - public void testLayout1KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("1 key L2 columns", 1, params.mNumColumns); - assertEquals("1 key L2 rows", 1, params.mNumRows); - assertEquals("1 key L2 left", 0, params.mLeftKeys); - assertEquals("1 key L2 right", 1, params.mRightKeys); - assertEquals("1 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [1]| - public void testLayout1KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("1 key R0 columns", 1, params.mNumColumns); - assertEquals("1 key R0 rows", 1, params.mNumRows); - assertEquals("1 key R0 left", 0, params.mLeftKeys); - assertEquals("1 key R0 right", 1, params.mRightKeys); - assertEquals("1 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key R0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [1] ___| - public void testLayout1KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("1 key R1 columns", 1, params.mNumColumns); - assertEquals("1 key R1 rows", 1, params.mNumRows); - assertEquals("1 key R1 left", 0, params.mLeftKeys); - assertEquals("1 key R1 right", 1, params.mRightKeys); - assertEquals("1 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key R1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [1] ___ ___| - public void testLayout1KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(1, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("1 key R2 columns", 1, params.mNumColumns); - assertEquals("1 key R2 rows", 1, params.mNumRows); - assertEquals("1 key R2 left", 0, params.mLeftKeys); - assertEquals("1 key R2 right", 1, params.mRightKeys); - assertEquals("1 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("1 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("1 key R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [1] [2] - public void testLayout2KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("2 key M0 columns", 2, params.mNumColumns); - assertEquals("2 key M0 rows", 1, params.mNumRows); - assertEquals("2 key M0 left", 0, params.mLeftKeys); - assertEquals("2 key M0 right", 2, params.mRightKeys); - assertEquals("2 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("2 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |[1] [2] - public void testLayout2KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("2 key L0 columns", 2, params.mNumColumns); - assertEquals("2 key L0 rows", 1, params.mNumRows); - assertEquals("2 key L0 left", 0, params.mLeftKeys); - assertEquals("2 key L0 right", 2, params.mRightKeys); - assertEquals("2 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("2 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [1] [2] - public void testLayout2KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("2 key L1 columns", 2, params.mNumColumns); - assertEquals("2 key L1 rows", 1, params.mNumRows); - assertEquals("2 key L1 left", 0, params.mLeftKeys); - assertEquals("2 key L1 right", 2, params.mRightKeys); - assertEquals("2 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("2 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [1] [2] - public void testLayout2KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("2 key L2 columns", 2, params.mNumColumns); - assertEquals("2 key L2 rows", 1, params.mNumRows); - assertEquals("2 key L2 left", 0, params.mLeftKeys); - assertEquals("2 key L2 right", 2, params.mRightKeys); - assertEquals("2 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("2 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [2] [1]| - public void testLayout2KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("2 key R0 columns", 2, params.mNumColumns); - assertEquals("2 key R0 rows", 1, params.mNumRows); - assertEquals("2 key R0 left", 1, params.mLeftKeys); - assertEquals("2 key R0 right", 1, params.mRightKeys); - assertEquals("2 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("2 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [2] [1] ___| - public void testLayout2KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("2 key R1 columns", 2, params.mNumColumns); - assertEquals("2 key R1 rows", 1, params.mNumRows); - assertEquals("2 key R1 left", 1, params.mLeftKeys); - assertEquals("2 key R1 right", 1, params.mRightKeys); - assertEquals("2 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("2 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [1] [2] ___ ___| - public void testLayout2KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(2, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("2 key R2 columns", 2, params.mNumColumns); - assertEquals("2 key R2 rows", 1, params.mNumRows); - assertEquals("2 key R2 left", 0, params.mLeftKeys); - assertEquals("2 key R2 right", 2, params.mRightKeys); - assertEquals("2 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("2 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("2 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("2 key R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // [3] [1] [2] - public void testLayout3KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("3 key columns", 3, params.mNumColumns); - assertEquals("3 key rows", 1, params.mNumRows); - assertEquals("3 key left", 1, params.mLeftKeys); - assertEquals("3 key right", 2, params.mRightKeys); - assertEquals("3 key [1]", 0, params.getColumnPos(0)); - assertEquals("3 key [2]", 1, params.getColumnPos(1)); - assertEquals("3 key [3]", -1, params.getColumnPos(2)); - assertEquals("3 key adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // |[1] [2] [3] - public void testLayout3KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("3 key L0 columns", 3, params.mNumColumns); - assertEquals("3 key L0 rows", 1, params.mNumRows); - assertEquals("3 key L0 left", 0, params.mLeftKeys); - assertEquals("3 key L0 right", 3, params.mRightKeys); - assertEquals("3 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("3 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("3 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [1] [2] [3] - public void testLayout3KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("3 key L1 columns", 3, params.mNumColumns); - assertEquals("3 key L1 rows", 1, params.mNumRows); - assertEquals("3 key L1 left", 0, params.mLeftKeys); - assertEquals("3 key L1 right", 3, params.mRightKeys); - assertEquals("3 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("3 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("3 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [3] [1] [2] - public void testLayout3KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("3 key L2 columns", 3, params.mNumColumns); - assertEquals("3 key L2 rows", 1, params.mNumRows); - assertEquals("3 key L2 left", 1, params.mLeftKeys); - assertEquals("3 key L2 right", 2, params.mRightKeys); - assertEquals("3 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("3 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("3 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [3] [2] [1]| - public void testLayout3KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("3 key R0 columns", 3, params.mNumColumns); - assertEquals("3 key R0 rows", 1, params.mNumRows); - assertEquals("3 key R0 left", 2, params.mLeftKeys); - assertEquals("3 key R0 right", 1, params.mRightKeys); - assertEquals("3 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("3 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("3 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [3] [2] [1] ___| - public void testLayout3KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("3 key R1 columns", 3, params.mNumColumns); - assertEquals("3 key R1 rows", 1, params.mNumRows); - assertEquals("3 key R1 left", 2, params.mLeftKeys); - assertEquals("3 key R1 right", 1, params.mRightKeys); - assertEquals("3 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("3 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("3 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [3] [1] [2] ___ ___| - public void testLayout3KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(3, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("3 key R2 columns", 3, params.mNumColumns); - assertEquals("3 key R2 rows", 1, params.mNumRows); - assertEquals("3 key R2 left", 1, params.mLeftKeys); - assertEquals("3 key R2 right", 2, params.mRightKeys); - assertEquals("3 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("3 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("3 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("3 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("3 key R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [3] [1] [2] [4] - public void testLayout4KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("4 key columns", 4, params.mNumColumns); - assertEquals("4 key rows", 1, params.mNumRows); - assertEquals("4 key left", 1, params.mLeftKeys); - assertEquals("4 key right", 3, params.mRightKeys); - assertEquals("4 key [1]", 0, params.getColumnPos(0)); - assertEquals("4 key [2]", 1, params.getColumnPos(1)); - assertEquals("4 key [3]", -1, params.getColumnPos(2)); - assertEquals("4 key [4]", 2, params.getColumnPos(3)); - assertEquals("4 key adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // |[1] [2] [3] [4] - public void testLayout4KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("4 key L0 columns", 4, params.mNumColumns); - assertEquals("4 key L0 rows", 1, params.mNumRows); - assertEquals("4 key L0 left", 0, params.mLeftKeys); - assertEquals("4 key L0 right", 4, params.mRightKeys); - assertEquals("4 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("4 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("4 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("4 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [1] [2] [3] [4] - public void testLayout4KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("4 key L1 columns", 4, params.mNumColumns); - assertEquals("4 key L1 rows", 1, params.mNumRows); - assertEquals("4 key L1 left", 0, params.mLeftKeys); - assertEquals("4 key L1 right", 4, params.mRightKeys); - assertEquals("4 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("4 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("4 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("4 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [3] [1] [2] [4] - public void testLayout4KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("4 key L2 columns", 4, params.mNumColumns); - assertEquals("4 key L2 rows", 1, params.mNumRows); - assertEquals("4 key L2 left", 1, params.mLeftKeys); - assertEquals("4 key L2 right", 3, params.mRightKeys); - assertEquals("4 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("4 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("4 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("4 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [4] [3] [2] [1]| - public void testLayout4KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("4 key R0 columns", 4, params.mNumColumns); - assertEquals("4 key R0 rows", 1, params.mNumRows); - assertEquals("4 key R0 left", 3, params.mLeftKeys); - assertEquals("4 key R0 right", 1, params.mRightKeys); - assertEquals("4 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("4 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("4 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("4 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [4] [3] [2] [1] ___| - public void testLayout4KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("4 key R1 columns", 4, params.mNumColumns); - assertEquals("4 key R1 rows", 1, params.mNumRows); - assertEquals("4 key R1 left", 3, params.mLeftKeys); - assertEquals("4 key R1 right", 1, params.mRightKeys); - assertEquals("4 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("4 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("4 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("4 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [4] [3] [1] [2] ___ ___| - public void testLayout4KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(4, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("4 key R2 columns", 4, params.mNumColumns); - assertEquals("4 key R2 rows", 1, params.mNumRows); - assertEquals("4 key R2 left", 2, params.mLeftKeys); - assertEquals("4 key R2 right", 2, params.mRightKeys); - assertEquals("4 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("4 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("4 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("4 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("4 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("4 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [5] [3] [1] [2] [4] - public void testLayout5KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("5 key columns", 5, params.mNumColumns); - assertEquals("5 key rows", 1, params.mNumRows); - assertEquals("5 key left", 2, params.mLeftKeys); - assertEquals("5 key right", 3, params.mRightKeys); - assertEquals("5 key [1]", 0, params.getColumnPos(0)); - assertEquals("5 key [2]", 1, params.getColumnPos(1)); - assertEquals("5 key [3]", -1, params.getColumnPos(2)); - assertEquals("5 key [4]", 2, params.getColumnPos(3)); - assertEquals("5 key [5]", -2, params.getColumnPos(4)); - assertEquals("5 key adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // |[1] [2] [3] [4] [5] - public void testLayout5KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("5 key L0 columns", 5, params.mNumColumns); - assertEquals("5 key L0 rows", 1, params.mNumRows); - assertEquals("5 key L0 left", 0, params.mLeftKeys); - assertEquals("5 key L0 right", 5, params.mRightKeys); - assertEquals("5 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("5 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("5 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("5 key L0 [5]", 4, params.getColumnPos(4)); - assertEquals("5 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [1] [2] [3] [4] [5] - public void testLayout5KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("5 key L1 columns", 5, params.mNumColumns); - assertEquals("5 key L1 rows", 1, params.mNumRows); - assertEquals("5 key L1 left", 0, params.mLeftKeys); - assertEquals("5 key L1 right", 5, params.mRightKeys); - assertEquals("5 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("5 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("5 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("5 key L1 [5]", 4, params.getColumnPos(4)); - assertEquals("5 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [3] [1] [2] [4] [5] - public void testLayout5KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("5 key L2 columns", 5, params.mNumColumns); - assertEquals("5 key L2 rows", 1, params.mNumRows); - assertEquals("5 key L2 left", 1, params.mLeftKeys); - assertEquals("5 key L2 right", 4, params.mRightKeys); - assertEquals("5 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("5 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("5 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("5 key L2 [5]", 3, params.getColumnPos(4)); - assertEquals("5 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [5] [4] [3] [2] [1]| - public void testLayout5KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("5 key R0 columns", 5, params.mNumColumns); - assertEquals("5 key R0 rows", 1, params.mNumRows); - assertEquals("5 key R0 left", 4, params.mLeftKeys); - assertEquals("5 key R0 right", 1, params.mRightKeys); - assertEquals("5 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("5 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("5 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("5 key R0 [5]", -4, params.getColumnPos(4)); - assertEquals("5 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [5] [4] [3] [2] [1] ___| - public void testLayout5KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("5 key R1 columns", 5, params.mNumColumns); - assertEquals("5 key R1 rows", 1, params.mNumRows); - assertEquals("5 key R1 left", 4, params.mLeftKeys); - assertEquals("5 key R1 right", 1, params.mRightKeys); - assertEquals("5 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("5 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("5 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("5 key R1 [5]", -4, params.getColumnPos(4)); - assertEquals("5 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [5] [4] [3] [1] [2] ___ ___| - public void testLayout5KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(5, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("5 key R2 columns", 5, params.mNumColumns); - assertEquals("5 key R2 rows", 1, params.mNumRows); - assertEquals("5 key R2 left", 3, params.mLeftKeys); - assertEquals("5 key R2 right", 2, params.mRightKeys); - assertEquals("5 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("5 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("5 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("5 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("5 key R2 [5]", -3, params.getColumnPos(4)); - assertEquals("5 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("5 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [6] [4] [5] - // [3] [1] [2] - public void testLayout6KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("6 key columns", 3, params.mNumColumns); - assertEquals("6 key rows", 2, params.mNumRows); - assertEquals("6 key left", 1, params.mLeftKeys); - assertEquals("6 key right", 2, params.mRightKeys); - assertEquals("6 key [1]", 0, params.getColumnPos(0)); - assertEquals("6 key [2]", 1, params.getColumnPos(1)); - assertEquals("6 key [3]", -1, params.getColumnPos(2)); - assertEquals("6 key [4]", 0, params.getColumnPos(3)); - assertEquals("6 key [5]", 1, params.getColumnPos(4)); - assertEquals("6 key [6]", -1, params.getColumnPos(5)); - assertEquals("6 key adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // |[4] [5] [6] - // |[1] [2] [3] - public void testLayout6KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("6 key L0 columns", 3, params.mNumColumns); - assertEquals("6 key L0 rows", 2, params.mNumRows); - assertEquals("6 key L0 left", 0, params.mLeftKeys); - assertEquals("6 key L0 right", 3, params.mRightKeys); - assertEquals("6 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("6 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("6 key L0 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key L0 [5]", 1, params.getColumnPos(4)); - assertEquals("6 key L0 [6]", 2, params.getColumnPos(5)); - assertEquals("6 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [4] [5] [6] - // |___ [1] [2] [3] - public void testLayout6KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("6 key L1 columns", 3, params.mNumColumns); - assertEquals("6 key L1 rows", 2, params.mNumRows); - assertEquals("6 key L1 left", 0, params.mLeftKeys); - assertEquals("6 key L1 right", 3, params.mRightKeys); - assertEquals("6 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("6 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("6 key L1 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key L1 [5]", 1, params.getColumnPos(4)); - assertEquals("6 key L1 [6]", 2, params.getColumnPos(5)); - assertEquals("6 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [6] [4] [5] - // |___ ___ [3] [1] [2] - public void testLayout6KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("6 key L2 columns", 3, params.mNumColumns); - assertEquals("6 key L2 rows", 2, params.mNumRows); - assertEquals("6 key L2 left", 1, params.mLeftKeys); - assertEquals("6 key L2 right", 2, params.mRightKeys); - assertEquals("6 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("6 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("6 key L2 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key L2 [5]", 1, params.getColumnPos(4)); - assertEquals("6 key L2 [6]", -1, params.getColumnPos(5)); - assertEquals("6 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [6] [5] [4]| - // [3] [2] [1]| - public void testLayout6KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("6 key R0 columns", 3, params.mNumColumns); - assertEquals("6 key R0 rows", 2, params.mNumRows); - assertEquals("6 key R0 left", 2, params.mLeftKeys); - assertEquals("6 key R0 right", 1, params.mRightKeys); - assertEquals("6 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("6 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("6 key R0 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key R0 [5]", -1, params.getColumnPos(4)); - assertEquals("6 key R0 [6]", -2, params.getColumnPos(5)); - assertEquals("6 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [6] [5] [4] ___| - // [3] [2] [1] ___| - public void testLayout6KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("6 key R1 columns", 3, params.mNumColumns); - assertEquals("6 key R1 rows", 2, params.mNumRows); - assertEquals("6 key R1 left", 2, params.mLeftKeys); - assertEquals("6 key R1 right", 1, params.mRightKeys); - assertEquals("6 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("6 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("6 key R1 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key R1 [5]", -1, params.getColumnPos(4)); - assertEquals("6 key R1 [6]", -2, params.getColumnPos(5)); - assertEquals("6 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [6] [4] [5] ___ ___| - // [3] [1] [2] ___ ___| - public void testLayout6KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(6, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("6 key R2 columns", 3, params.mNumColumns); - assertEquals("6 key R2 rows", 2, params.mNumRows); - assertEquals("6 key R2 left", 1, params.mLeftKeys); - assertEquals("6 key R2 right", 2, params.mRightKeys); - assertEquals("6 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("6 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("6 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("6 key R2 [4]", 0, params.getColumnPos(3)); - assertEquals("6 key R2 [5]", 1, params.getColumnPos(4)); - assertEquals("6 key R2 [6]", -1, params.getColumnPos(5)); - assertEquals("6 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("6 key R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [7] [5] [6] - // [3] [1] [2] [4] - public void testLayout7KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("7 key columns", 4, params.mNumColumns); - assertEquals("7 key rows", 2, params.mNumRows); - assertEquals("7 key left", 1, params.mLeftKeys); - assertEquals("7 key right", 3, params.mRightKeys); - assertEquals("7 key [1]", 0, params.getColumnPos(0)); - assertEquals("7 key [2]", 1, params.getColumnPos(1)); - assertEquals("7 key [3]", -1, params.getColumnPos(2)); - assertEquals("7 key [4]", 2, params.getColumnPos(3)); - assertEquals("7 key [5]", 0, params.getColumnPos(4)); - assertEquals("7 key [6]", 1, params.getColumnPos(5)); - assertEquals("7 key [7]", -1, params.getColumnPos(6)); - assertEquals("7 key adjust", 1, params.mTopRowAdjustment); - assertEquals("7 key default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // |[5] [6] [7] - // |[1] [2] [3] [4] - public void testLayout7KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("7 key L0 columns", 4, params.mNumColumns); - assertEquals("7 key L0 rows", 2, params.mNumRows); - assertEquals("7 key L0 left", 0, params.mLeftKeys); - assertEquals("7 key L0 right", 4, params.mRightKeys); - assertEquals("7 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("7 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("7 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("7 key L0 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key L0 [6]", 1, params.getColumnPos(5)); - assertEquals("7 key L0 [7]", 2, params.getColumnPos(6)); - assertEquals("7 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("7 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [5] [6] [7] - // |___ [1] [2] [3] [4] - public void testLayout7KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("7 key L1 columns", 4, params.mNumColumns); - assertEquals("7 key L1 rows", 2, params.mNumRows); - assertEquals("7 key L1 left", 0, params.mLeftKeys); - assertEquals("7 key L1 right", 4, params.mRightKeys); - assertEquals("7 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("7 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("7 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("7 key L1 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key L1 [6]", 1, params.getColumnPos(5)); - assertEquals("7 key L1 [7]", 2, params.getColumnPos(6)); - assertEquals("7 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("7 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [7] [5] [6] - // |___ ___ [3] [1] [2] [4] - public void testLayout7KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("7 key L2 columns", 4, params.mNumColumns); - assertEquals("7 key L2 rows", 2, params.mNumRows); - assertEquals("7 key L2 left", 1, params.mLeftKeys); - assertEquals("7 key L2 right", 3, params.mRightKeys); - assertEquals("7 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("7 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("7 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("7 key L2 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key L2 [6]", 1, params.getColumnPos(5)); - assertEquals("7 key L2 [7]", -1, params.getColumnPos(6)); - assertEquals("7 key L2 adjust", 1, params.mTopRowAdjustment); - assertEquals("7 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [7] [6] [5]| - // [4] [3] [2] [1]| - public void testLayout7KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("7 key R0 columns", 4, params.mNumColumns); - assertEquals("7 key R0 rows", 2, params.mNumRows); - assertEquals("7 key R0 left", 3, params.mLeftKeys); - assertEquals("7 key R0 right", 1, params.mRightKeys); - assertEquals("7 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("7 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("7 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("7 key R0 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key R0 [6]", -1, params.getColumnPos(5)); - assertEquals("7 key R0 [7]", -2, params.getColumnPos(6)); - assertEquals("7 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("7 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [7] [6] [5] ___| - // [4] [3] [2] [1] ___| - public void testLayout7KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("7 key R1 columns", 4, params.mNumColumns); - assertEquals("7 key R1 rows", 2, params.mNumRows); - assertEquals("7 key R1 left", 3, params.mLeftKeys); - assertEquals("7 key R1 right", 1, params.mRightKeys); - assertEquals("7 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("7 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("7 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("7 key R1 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key R1 [6]", -1, params.getColumnPos(5)); - assertEquals("7 key R1 [7]", -2, params.getColumnPos(6)); - assertEquals("7 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("7 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [7] [5] [6] ___ ___| - // [4] [3] [1] [2] ___ ___| - public void testLayout7KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(7, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("7 key R2 columns", 4, params.mNumColumns); - assertEquals("7 key R2 rows", 2, params.mNumRows); - assertEquals("7 key R2 left", 2, params.mLeftKeys); - assertEquals("7 key R2 right", 2, params.mRightKeys); - assertEquals("7 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("7 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("7 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("7 key R2 [5]", 0, params.getColumnPos(4)); - assertEquals("7 key R2 [6]", 1, params.getColumnPos(5)); - assertEquals("7 key R2 [7]", -1, params.getColumnPos(6)); - assertEquals("7 key R2 adjust", -1, params.mTopRowAdjustment); - assertEquals("7 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [7] [6] [5] [3] [1] [2] [4] ___| - public void testLayout7KeyR3Max7() { - MiniKeyboardParams params = new MiniKeyboardParams(7, 7, WIDTH, - HEIGHT, XPOS_R3, KEYBOARD_WIDTH); - assertEquals("7 key R2 columns", 7, params.mNumColumns); - assertEquals("7 key R2 rows", 1, params.mNumRows); - assertEquals("7 key R2 left", 4, params.mLeftKeys); - assertEquals("7 key R2 right", 3, params.mRightKeys); - assertEquals("7 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("7 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("7 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("7 key R2 [4]", 2, params.getColumnPos(3)); - assertEquals("7 key R2 [5]", -2, params.getColumnPos(4)); - assertEquals("7 key R2 [6]", -3, params.getColumnPos(5)); - assertEquals("7 key R2 [7]", -4, params.getColumnPos(6)); - assertEquals("7 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("7 key R2 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [7] [5] [6] [8] - // [3] [1] [2] [4] - public void testLayout8KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("8 key M0 columns", 4, params.mNumColumns); - assertEquals("8 key M0 rows", 2, params.mNumRows); - assertEquals("8 key M0 left", 1, params.mLeftKeys); - assertEquals("8 key M0 right", 3, params.mRightKeys); - assertEquals("8 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("8 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("8 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("8 key M0 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key M0 [6]", 1, params.getColumnPos(5)); - assertEquals("8 key M0 [7]", -1, params.getColumnPos(6)); - assertEquals("8 key M0 [8]", 2, params.getColumnPos(7)); - assertEquals("8 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // |[5] [6] [7] [8] - // |[1] [2] [3] [4] - public void testLayout8KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("8 key L0 columns", 4, params.mNumColumns); - assertEquals("8 key L0 rows", 2, params.mNumRows); - assertEquals("8 key L0 left", 0, params.mLeftKeys); - assertEquals("8 key L0 right", 4, params.mRightKeys); - assertEquals("8 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("8 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("8 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("8 key L0 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key L0 [6]", 1, params.getColumnPos(5)); - assertEquals("8 key L0 [7]", 2, params.getColumnPos(6)); - assertEquals("8 key L0 [8]", 3, params.getColumnPos(7)); - assertEquals("8 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [5] [6] [7] [8] - // |___ [1] [2] [3] [4] - public void testLayout8KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("8 key L1 columns", 4, params.mNumColumns); - assertEquals("8 key L1 rows", 2, params.mNumRows); - assertEquals("8 key L1 left", 0, params.mLeftKeys); - assertEquals("8 key L1 right", 4, params.mRightKeys); - assertEquals("8 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("8 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("8 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("8 key L1 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key L1 [6]", 1, params.getColumnPos(5)); - assertEquals("8 key L1 [7]", 2, params.getColumnPos(6)); - assertEquals("8 key L1 [8]", 3, params.getColumnPos(7)); - assertEquals("8 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [7] [5] [6] [8] - // |___ ___ [3] [1] [2] [4] - public void testLayout8KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("8 key L2 columns", 4, params.mNumColumns); - assertEquals("8 key L2 rows", 2, params.mNumRows); - assertEquals("8 key L2 left", 1, params.mLeftKeys); - assertEquals("8 key L2 right", 3, params.mRightKeys); - assertEquals("8 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("8 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("8 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("8 key L2 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key L2 [6]", 1, params.getColumnPos(5)); - assertEquals("8 key L2 [7]", -1, params.getColumnPos(6)); - assertEquals("8 key L2 [8]", 2, params.getColumnPos(7)); - assertEquals("8 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [8] [7] [6] [5]| - // [4] [3] [2] [1]| - public void testLayout8KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("8 key R0 columns", 4, params.mNumColumns); - assertEquals("8 key R0 rows", 2, params.mNumRows); - assertEquals("8 key R0 left", 3, params.mLeftKeys); - assertEquals("8 key R0 right", 1, params.mRightKeys); - assertEquals("8 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("8 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("8 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("8 key R0 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key R0 [6]", -1, params.getColumnPos(5)); - assertEquals("8 key R0 [7]", -2, params.getColumnPos(6)); - assertEquals("8 key R0 [8]", -3, params.getColumnPos(7)); - assertEquals("8 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [8] [7] [6] [5] ___| - // [4] [3] [2] [1] ___| - public void testLayout8KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("8 key R1 columns", 4, params.mNumColumns); - assertEquals("8 key R1 rows", 2, params.mNumRows); - assertEquals("8 key R1 left", 3, params.mLeftKeys); - assertEquals("8 key R1 right", 1, params.mRightKeys); - assertEquals("8 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("8 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("8 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("8 key R1 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key R1 [6]", -1, params.getColumnPos(5)); - assertEquals("8 key R1 [7]", -2, params.getColumnPos(6)); - assertEquals("8 key R1 [8]", -3, params.getColumnPos(7)); - assertEquals("8 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [8] [7] [5] [6] ___ ___| - // [4] [3] [1] [2] ___ ___| - public void testLayout8KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(8, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("8 key R2 columns", 4, params.mNumColumns); - assertEquals("8 key R2 rows", 2, params.mNumRows); - assertEquals("8 key R2 left", 2, params.mLeftKeys); - assertEquals("8 key R2 right", 2, params.mRightKeys); - assertEquals("8 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("8 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("8 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("8 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("8 key R2 [5]", 0, params.getColumnPos(4)); - assertEquals("8 key R2 [6]", 1, params.getColumnPos(5)); - assertEquals("8 key R2 [7]", -1, params.getColumnPos(6)); - assertEquals("8 key R2 [8]", -2, params.getColumnPos(7)); - assertEquals("8 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("8 key R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // [8] [6] [7] [9] - // [5] [3] [1] [2] [4] - public void testLayout9KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("9 key M0 columns", 5, params.mNumColumns); - assertEquals("9 key M0 rows", 2, params.mNumRows); - assertEquals("9 key M0 left", 2, params.mLeftKeys); - assertEquals("9 key M0 right", 3, params.mRightKeys); - assertEquals("9 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("9 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("9 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("9 key M0 [5]", -2, params.getColumnPos(4)); - assertEquals("9 key M0 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key M0 [7]", 1, params.getColumnPos(6)); - assertEquals("9 key M0 [8]", -1, params.getColumnPos(7)); - assertEquals("9 key M0 [9]", 2, params.getColumnPos(8)); - assertEquals("9 key M0 adjust", -1, params.mTopRowAdjustment); - assertEquals("9 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // |[6] [7] [8] [9] - // |[1] [2] [3] [4] [5] - public void testLayout9KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("9 key L0 columns", 5, params.mNumColumns); - assertEquals("9 key L0 rows", 2, params.mNumRows); - assertEquals("9 key L0 left", 0, params.mLeftKeys); - assertEquals("9 key L0 right", 5, params.mRightKeys); - assertEquals("9 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("9 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("9 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("9 key L0 [5]", 4, params.getColumnPos(4)); - assertEquals("9 key L0 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key L0 [7]", 1, params.getColumnPos(6)); - assertEquals("9 key L0 [8]", 2, params.getColumnPos(7)); - assertEquals("9 key L0 [9]", 3, params.getColumnPos(8)); - assertEquals("9 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("9 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [6] [7] [8] [9] - // |___ [1] [2] [3] [4] [5] - public void testLayout9KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("9 key L1 columns", 5, params.mNumColumns); - assertEquals("9 key L1 rows", 2, params.mNumRows); - assertEquals("9 key L1 left", 0, params.mLeftKeys); - assertEquals("9 key L1 right", 5, params.mRightKeys); - assertEquals("9 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("9 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("9 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("9 key L1 [5]", 4, params.getColumnPos(4)); - assertEquals("9 key L1 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key L1 [7]", 1, params.getColumnPos(6)); - assertEquals("9 key L1 [8]", 2, params.getColumnPos(7)); - assertEquals("9 key L1 [9]", 3, params.getColumnPos(8)); - assertEquals("9 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("9 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [8] [6] [7] [9] - // |___ ___ [3] [1] [2] [4] [5] - public void testLayout9KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("9 key L2 columns", 5, params.mNumColumns); - assertEquals("9 key L2 rows", 2, params.mNumRows); - assertEquals("9 key L2 left", 1, params.mLeftKeys); - assertEquals("9 key L2 right", 4, params.mRightKeys); - assertEquals("9 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("9 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("9 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("9 key L2 [5]", 3, params.getColumnPos(4)); - assertEquals("9 key L2 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key L2 [7]", 1, params.getColumnPos(6)); - assertEquals("9 key L2 [8]", -1, params.getColumnPos(7)); - assertEquals("9 key L2 [9]", 2, params.getColumnPos(8)); - assertEquals("9 key L2 adjust", 1, params.mTopRowAdjustment); - assertEquals("9 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [9] [8] [7] [6]| - // [5] [4] [3] [2] [1]| - public void testLayout9KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("9 key R0 columns", 5, params.mNumColumns); - assertEquals("9 key R0 rows", 2, params.mNumRows); - assertEquals("9 key R0 left", 4, params.mLeftKeys); - assertEquals("9 key R0 right", 1, params.mRightKeys); - assertEquals("9 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("9 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("9 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("9 key R0 [5]", -4, params.getColumnPos(4)); - assertEquals("9 key R0 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key R0 [7]", -1, params.getColumnPos(6)); - assertEquals("9 key R0 [8]", -2, params.getColumnPos(7)); - assertEquals("9 key R0 [9]", -3, params.getColumnPos(8)); - assertEquals("9 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("9 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [9] [8] [7] [6] ___| - // [5] [4] [3] [2] [1] ___| - public void testLayout9KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("9 key R1 columns", 5, params.mNumColumns); - assertEquals("9 key R1 rows", 2, params.mNumRows); - assertEquals("9 key R1 left", 4, params.mLeftKeys); - assertEquals("9 key R1 right", 1, params.mRightKeys); - assertEquals("9 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("9 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("9 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("9 key R1 [5]", -4, params.getColumnPos(4)); - assertEquals("9 key R1 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key R1 [7]", -1, params.getColumnPos(6)); - assertEquals("9 key R1 [8]", -2, params.getColumnPos(7)); - assertEquals("9 key R1 [9]", -3, params.getColumnPos(8)); - assertEquals("9 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("9 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [9] [8] [6] [7] ___ ___| - // [5] [4] [3] [1] [2] ___ ___| - public void testLayout9KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(9, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("9 key R2 columns", 5, params.mNumColumns); - assertEquals("9 key R2 rows", 2, params.mNumRows); - assertEquals("9 key R2 left", 3, params.mLeftKeys); - assertEquals("9 key R2 right", 2, params.mRightKeys); - assertEquals("9 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("9 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("9 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("9 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("9 key R2 [5]", -3, params.getColumnPos(4)); - assertEquals("9 key R2 [6]", 0, params.getColumnPos(5)); - assertEquals("9 key R2 [7]", 1, params.getColumnPos(6)); - assertEquals("9 key R2 [8]", -1, params.getColumnPos(7)); - assertEquals("9 key R2 [9]", -2, params.getColumnPos(8)); - assertEquals("9 key R2 adjust", -1, params.mTopRowAdjustment); - assertEquals("9 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [A] [8] [6] [7] [9] - // [5] [3] [1] [2] [4] - public void testLayout10KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("10 key M0 columns", 5, params.mNumColumns); - assertEquals("10 key M0 rows", 2, params.mNumRows); - assertEquals("10 key M0 left", 2, params.mLeftKeys); - assertEquals("10 key M0 right", 3, params.mRightKeys); - assertEquals("10 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("10 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("10 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("10 key M0 [5]", -2, params.getColumnPos(4)); - assertEquals("10 key M0 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key M0 [7]", 1, params.getColumnPos(6)); - assertEquals("10 key M0 [8]", -1, params.getColumnPos(7)); - assertEquals("10 key M0 [9]", 2, params.getColumnPos(8)); - assertEquals("10 key M0 [A]", -2, params.getColumnPos(9)); - assertEquals("10 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } - - // |[6] [7] [8] [9] [A] - // |[1] [2] [3] [4] [5] - public void testLayout10KeyL0() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L0, KEYBOARD_WIDTH); - assertEquals("10 key L0 columns", 5, params.mNumColumns); - assertEquals("10 key L0 rows", 2, params.mNumRows); - assertEquals("10 key L0 left", 0, params.mLeftKeys); - assertEquals("10 key L0 right", 5, params.mRightKeys); - assertEquals("10 key L0 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key L0 [2]", 1, params.getColumnPos(1)); - assertEquals("10 key L0 [3]", 2, params.getColumnPos(2)); - assertEquals("10 key L0 [4]", 3, params.getColumnPos(3)); - assertEquals("10 key L0 [5]", 4, params.getColumnPos(4)); - assertEquals("10 key L0 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key L0 [7]", 1, params.getColumnPos(6)); - assertEquals("10 key L0 [8]", 2, params.getColumnPos(7)); - assertEquals("10 key L0 [9]", 3, params.getColumnPos(8)); - assertEquals("10 key L0 [A]", 4, params.getColumnPos(9)); - assertEquals("10 key L0 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ [6] [7] [8] [9] [A] - // |___ [1] [2] [3] [4] [5] - public void testLayout10KeyL1() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L1, KEYBOARD_WIDTH); - assertEquals("10 key L1 columns", 5, params.mNumColumns); - assertEquals("10 key L1 rows", 2, params.mNumRows); - assertEquals("10 key L1 left", 0, params.mLeftKeys); - assertEquals("10 key L1 right", 5, params.mRightKeys); - assertEquals("10 key L1 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key L1 [2]", 1, params.getColumnPos(1)); - assertEquals("10 key L1 [3]", 2, params.getColumnPos(2)); - assertEquals("10 key L1 [4]", 3, params.getColumnPos(3)); - assertEquals("10 key L1 [5]", 4, params.getColumnPos(4)); - assertEquals("10 key L1 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key L1 [7]", 1, params.getColumnPos(6)); - assertEquals("10 key L1 [8]", 2, params.getColumnPos(7)); - assertEquals("10 key L1 [9]", 3, params.getColumnPos(8)); - assertEquals("10 key L1 [A]", 4, params.getColumnPos(9)); - assertEquals("10 key L1 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); - } - - // |___ ___ [8] [6] [7] [9] [A] - // |___ ___ [3] [1] [2] [4] [5] - public void testLayout10KeyL2() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_L2, KEYBOARD_WIDTH); - assertEquals("10 key L2 columns", 5, params.mNumColumns); - assertEquals("10 key L2 rows", 2, params.mNumRows); - assertEquals("10 key L2 left", 1, params.mLeftKeys); - assertEquals("10 key L2 right", 4, params.mRightKeys); - assertEquals("10 key L2 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key L2 [2]", 1, params.getColumnPos(1)); - assertEquals("10 key L2 [3]", -1, params.getColumnPos(2)); - assertEquals("10 key L2 [4]", 2, params.getColumnPos(3)); - assertEquals("10 key L2 [5]", 3, params.getColumnPos(4)); - assertEquals("10 key L2 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key L2 [7]", 1, params.getColumnPos(6)); - assertEquals("10 key L2 [8]", -1, params.getColumnPos(7)); - assertEquals("10 key L2 [9]", 2, params.getColumnPos(8)); - assertEquals("10 key L2 [A]", 3, params.getColumnPos(9)); - assertEquals("10 key L2 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [A] [9] [8] [7] [6]| - // [5] [4] [3] [2] [1]| - public void testLayout10KeyR0() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R0, KEYBOARD_WIDTH); - assertEquals("10 key R0 columns", 5, params.mNumColumns); - assertEquals("10 key R0 rows", 2, params.mNumRows); - assertEquals("10 key R0 left", 4, params.mLeftKeys); - assertEquals("10 key R0 right", 1, params.mRightKeys); - assertEquals("10 key R0 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key R0 [2]", -1, params.getColumnPos(1)); - assertEquals("10 key R0 [3]", -2, params.getColumnPos(2)); - assertEquals("10 key R0 [4]", -3, params.getColumnPos(3)); - assertEquals("10 key R0 [5]", -4, params.getColumnPos(4)); - assertEquals("10 key R0 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key R0 [7]", -1, params.getColumnPos(6)); - assertEquals("10 key R0 [8]", -2, params.getColumnPos(7)); - assertEquals("10 key R0 [9]", -3, params.getColumnPos(8)); - assertEquals("10 key R0 [A]", -4, params.getColumnPos(9)); - assertEquals("10 key R0 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [A] [9] [8] [7] [6] ___| - // [5] [4] [3] [2] [1] ___| - public void testLayout10KeyR1() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R1, KEYBOARD_WIDTH); - assertEquals("10 key R1 columns", 5, params.mNumColumns); - assertEquals("10 key R1 rows", 2, params.mNumRows); - assertEquals("10 key R1 left", 4, params.mLeftKeys); - assertEquals("10 key R1 right", 1, params.mRightKeys); - assertEquals("10 key R1 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key R1 [2]", -1, params.getColumnPos(1)); - assertEquals("10 key R1 [3]", -2, params.getColumnPos(2)); - assertEquals("10 key R1 [4]", -3, params.getColumnPos(3)); - assertEquals("10 key R1 [5]", -4, params.getColumnPos(4)); - assertEquals("10 key R1 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key R1 [7]", -1, params.getColumnPos(6)); - assertEquals("10 key R1 [8]", -2, params.getColumnPos(7)); - assertEquals("10 key R1 [9]", -3, params.getColumnPos(8)); - assertEquals("10 key R1 [A]", -4, params.getColumnPos(9)); - assertEquals("10 key R1 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); - } - - // [A] [9] [8] [6] [7] ___ ___| - // [5] [4] [3] [1] [2] ___ ___| - public void testLayout10KeyR2() { - MiniKeyboardParams params = new MiniKeyboardParams(10, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_R2, KEYBOARD_WIDTH); - assertEquals("10 key R2 columns", 5, params.mNumColumns); - assertEquals("10 key R2 rows", 2, params.mNumRows); - assertEquals("10 key R2 left", 3, params.mLeftKeys); - assertEquals("10 key R2 right", 2, params.mRightKeys); - assertEquals("10 key R2 [1]", 0, params.getColumnPos(0)); - assertEquals("10 key R2 [2]", 1, params.getColumnPos(1)); - assertEquals("10 key R2 [3]", -1, params.getColumnPos(2)); - assertEquals("10 key R2 [4]", -2, params.getColumnPos(3)); - assertEquals("10 key R2 [5]", -3, params.getColumnPos(4)); - assertEquals("10 key R2 [6]", 0, params.getColumnPos(5)); - assertEquals("10 key R2 [7]", 1, params.getColumnPos(6)); - assertEquals("10 key R2 [8]", -1, params.getColumnPos(7)); - assertEquals("10 key R2 [9]", -2, params.getColumnPos(8)); - assertEquals("10 key R2 [A]", -3, params.getColumnPos(9)); - assertEquals("10 key R2 adjust", 0, params.mTopRowAdjustment); - assertEquals("10 key R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); - } - - // [B] [9] [A] - // [7] [5] [6] [8] - // [3] [1] [2] [4] - public void testLayout11KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(11, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("11 key M0 columns", 4, params.mNumColumns); - assertEquals("11 key M0 rows", 3, params.mNumRows); - assertEquals("11 key M0 left", 1, params.mLeftKeys); - assertEquals("11 key M0 right", 3, params.mRightKeys); - assertEquals("11 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("11 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("11 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("11 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("11 key M0 [5]", 0, params.getColumnPos(4)); - assertEquals("11 key M0 [6]", 1, params.getColumnPos(5)); - assertEquals("11 key M0 [7]", -1, params.getColumnPos(6)); - assertEquals("11 key M0 [8]", 2, params.getColumnPos(7)); - assertEquals("11 key M0 [9]", 0, params.getColumnPos(8)); - assertEquals("11 key M0 [A]", 1, params.getColumnPos(9)); - assertEquals("11 key M0 [B]", -1, params.getColumnPos(10)); - assertEquals("11 key M0 adjust", 1, params.mTopRowAdjustment); - assertEquals("11 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - // [B] [9] [A] [C] - // [7] [5] [6] [8] - // [3] [1] [2] [4] - public void testLayout12KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(12, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("12 key M0 columns", 4, params.mNumColumns); - assertEquals("12 key M0 rows", 3, params.mNumRows); - assertEquals("12 key M0 left", 1, params.mLeftKeys); - assertEquals("12 key M0 right", 3, params.mRightKeys); - assertEquals("12 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("12 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("12 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("12 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("12 key M0 [5]", 0, params.getColumnPos(4)); - assertEquals("12 key M0 [6]", 1, params.getColumnPos(5)); - assertEquals("12 key M0 [7]", -1, params.getColumnPos(6)); - assertEquals("12 key M0 [8]", 2, params.getColumnPos(7)); - assertEquals("12 key M0 [9]", 0, params.getColumnPos(8)); - assertEquals("12 key M0 [A]", 1, params.getColumnPos(9)); - assertEquals("12 key M0 [B]", -1, params.getColumnPos(10)); - assertEquals("12 key M0 [C]", 2, params.getColumnPos(11)); - assertEquals("12 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("12 key M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); - } - - - // [D] [B] [C] - // [A] [8] [6] [7] [9] - // [5] [3] [1] [2] [4] - public void testLayout13KeyM0() { - MiniKeyboardParams params = new MiniKeyboardParams(13, MAX_COLUMNS, WIDTH, - HEIGHT, XPOS_M0, KEYBOARD_WIDTH); - assertEquals("13 key M0 columns", 5, params.mNumColumns); - assertEquals("13 key M0 rows", 3, params.mNumRows); - assertEquals("13 key M0 left", 2, params.mLeftKeys); - assertEquals("13 key M0 right", 3, params.mRightKeys); - assertEquals("13 key M0 [1]", 0, params.getColumnPos(0)); - assertEquals("13 key M0 [2]", 1, params.getColumnPos(1)); - assertEquals("13 key M0 [3]", -1, params.getColumnPos(2)); - assertEquals("13 key M0 [4]", 2, params.getColumnPos(3)); - assertEquals("13 key M0 [5]", -2, params.getColumnPos(4)); - assertEquals("13 key M0 [6]", 0, params.getColumnPos(5)); - assertEquals("13 key M0 [7]", 1, params.getColumnPos(6)); - assertEquals("13 key M0 [8]", -1, params.getColumnPos(7)); - assertEquals("13 key M0 [9]", 2, params.getColumnPos(8)); - assertEquals("13 key M0 [A]", -2, params.getColumnPos(9)); - assertEquals("13 key M0 [B]", 0, params.getColumnPos(10)); - assertEquals("13 key M0 [C]", 1, params.getColumnPos(11)); - assertEquals("13 key M0 [D]", -1, params.getColumnPos(12)); - assertEquals("13 key M0 adjust", 0, params.mTopRowAdjustment); - assertEquals("13 key M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); - } -} diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java new file mode 100644 index 000000000..5c6c83432 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderFixedOrderTests.java @@ -0,0 +1,2631 @@ +/* + * 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.keyboard; + +import android.test.AndroidTestCase; + +import com.android.inputmethod.keyboard.MoreKeysKeyboard.Builder.MoreKeysKeyboardParams; + +public class MoreKeysKeyboardBuilderFixedOrderTests extends AndroidTestCase { + private static final int WIDTH = 10; + private static final int HEIGHT = 10; + + private static final int KEYBOARD_WIDTH = WIDTH * 10; + private static final int XPOS_L0 = WIDTH * 0 + WIDTH / 2; + private static final int XPOS_L1 = WIDTH * 1 + WIDTH / 2; + private static final int XPOS_L2 = WIDTH * 2 + WIDTH / 2; + private static final int XPOS_L3 = WIDTH * 3 + WIDTH / 2; + private static final int XPOS_M0 = WIDTH * 4 + WIDTH / 2; + private static final int XPOS_M1 = WIDTH * 5 + WIDTH / 2; + private static final int XPOS_R3 = WIDTH * 6 + WIDTH / 2; + private static final int XPOS_R2 = WIDTH * 7 + WIDTH / 2; + private static final int XPOS_R1 = WIDTH * 8 + WIDTH / 2; + private static final int XPOS_R0 = WIDTH * 9 + WIDTH / 2; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + private static MoreKeysKeyboardParams createParams(int numKeys, int columnNum, + int coordXInParnet) { + final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams(); + params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH, + /* isFixedOrderColumn */true, /* dividerWidth */0); + return params; + } + + public void testLayoutError() { + MoreKeysKeyboardParams params = null; + try { + final int fixColumns = KEYBOARD_WIDTH / WIDTH; + params = createParams(10, fixColumns + 1, HEIGHT); + fail("Should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Too small keyboard to hold more keys keyboard. + } + assertNull("Too small keyboard to hold more keys keyboard", params); + } + + // More keys keyboard layout test. + // "[n]" represents n-th key position in more keys keyboard. + // "<m>" is the default key. + + // <1> + public void testLayout1KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_M0); + assertEquals("1 key fix 5 M0 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 M0 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 M0 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 M0 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |<1> + public void testLayout1KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L0); + assertEquals("1 key fix 5 L0 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 L0 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 L0 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> + public void testLayout1KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L1); + assertEquals("1 key fix 5 L1 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 L1 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 L1 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ <1> + public void testLayout1KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L2); + assertEquals("1 key fix 5 L2 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 L2 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 L2 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 L2 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1>| + public void testLayout1KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R0); + assertEquals("1 key fix 5 R0 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 R0 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 R0 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 R0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> ___| + public void testLayout1KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R1); + assertEquals("1 key fix 5 R1 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 R1 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 R1 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 R1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> ___ ___| + public void testLayout1KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R2); + assertEquals("1 key fix 5 R2 columns", 1, params.mNumColumns); + assertEquals("1 key fix 5 R2 rows", 1, params.mNumRows); + assertEquals("1 key fix 5 R2 left", 0, params.mLeftKeys); + assertEquals("1 key fix 5 R2 right", 1, params.mRightKeys); + assertEquals("1 key fix 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key fix 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> [2] + public void testLayout2KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_M0); + assertEquals("2 key fix 5 M0 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 M0 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 M0 left", 0, params.mLeftKeys); + assertEquals("2 key fix 5 M0 right", 2, params.mRightKeys); + assertEquals("2 key fix 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key fix 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |<1> [2] + public void testLayout2KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L0); + assertEquals("2 key fix 5 L0 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 L0 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("2 key fix 5 L0 right", 2, params.mRightKeys); + assertEquals("2 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] + public void testLayout2KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L1); + assertEquals("2 key fix 5 L1 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 L1 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("2 key fix 5 L1 right", 2, params.mRightKeys); + assertEquals("2 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ <1> [2] + public void testLayout2KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L2); + assertEquals("2 key fix 5 L2 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 L2 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 L2 left", 0, params.mLeftKeys); + assertEquals("2 key fix 5 L2 right", 2, params.mRightKeys); + assertEquals("2 key fix 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key fix 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [1] <2>| + public void testLayout2KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R0); + assertEquals("2 key fix 5 R0 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 R0 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 R0 left", 1, params.mLeftKeys); + assertEquals("2 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("2 key fix 5 R0 [1]", -1, params.getColumnPos(0)); + assertEquals("2 key fix 5 R0 <2>", 0, params.getColumnPos(1)); + assertEquals("2 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [1] <2> ___| + public void testLayout2KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R1); + assertEquals("2 key fix 5 R1 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 R1 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 R1 left", 1, params.mLeftKeys); + assertEquals("2 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("2 key fix 5 R1 [1]", -1, params.getColumnPos(0)); + assertEquals("2 key fix 5 R1 <2>", 0, params.getColumnPos(1)); + assertEquals("2 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // <1> [2] ___| + public void testLayout2KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R2); + assertEquals("2 key fix 5 R2 columns", 2, params.mNumColumns); + assertEquals("2 key fix 5 R2 rows", 1, params.mNumRows); + assertEquals("2 key fix 5 R2 left", 0, params.mLeftKeys); + assertEquals("2 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("2 key fix 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key fix 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key fix 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] + // <1> [2] + public void testLayout3KeyFix2M0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_M0); + assertEquals("3 key fix 2 M0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 M0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 M0 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 M0 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 M0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |[3] + // |<1> [2] + public void testLayout3KeyFix2L0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L0); + assertEquals("3 key fix 2 L0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L0 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L0 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] + // |___ <1> [2] + public void testLayout3KeyFix2L1() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L1); + assertEquals("3 key fix 2 L1 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L1 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L1 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L1 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L1 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // | [3] + // |___ ___ <1> [2] + public void testLayout3KeyFix2L2() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L2); + assertEquals("3 key fix 2 L2 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L2 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L2 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L2 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3]| + // [1] <2>| + public void testLayout3KeyFix2R0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R0); + assertEquals("3 key fix 2 R0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R0 left", 1, params.mLeftKeys); + assertEquals("3 key fix 2 R0 right", 1, params.mRightKeys); + assertEquals("3 key fix 2 R0 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 2 R0 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 2 R0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] ___| + // [1] <2> ___| + public void testLayout3KeyFix2R1() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R1); + assertEquals("3 key fix 2 R1 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R1 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R1 left", 1, params.mLeftKeys); + assertEquals("3 key fix 2 R1 right", 1, params.mRightKeys); + assertEquals("3 key fix 2 R1 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 2 R1 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 2 R1 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] ___| + // <1> [2] ___| + public void testLayout3KeyFix2R2() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R2); + assertEquals("3 key fix 2 R2 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R2 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R2 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 R2 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 R2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] [4] + // <1> [2] + public void testLayout4KeyFix2M0() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_M0); + assertEquals("3 key fix 2 M0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 M0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 M0 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 M0 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 M0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("3 key fix 2 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |[3] [4] + // |<1> [2] + public void testLayout4KeyFix2L0() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_L0); + assertEquals("3 key fix 2 L0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L0 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L0 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L0 [4]", 1, params.getColumnPos(3)); + assertEquals("3 key fix 2 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] [4] + // |___ <1> [2] + public void testLayout4KeyFix2L1() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_L1); + assertEquals("3 key fix 2 L1 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L1 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L1 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L1 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L1 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L1 [4]", 1, params.getColumnPos(3)); + assertEquals("3 key fix 2 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // | [3] [4] + // |___ ___ <1> [2] + public void testLayout4KeyFix2L2() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_L2); + assertEquals("3 key fix 2 L2 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 L2 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 L2 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 L2 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 L2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 L2 [4]", 1, params.getColumnPos(3)); + assertEquals("3 key fix 2 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] [4]| + // [1] <2>| + public void testLayout4KeyFix2R0() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_R0); + assertEquals("3 key fix 2 R0 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R0 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R0 left", 1, params.mLeftKeys); + assertEquals("3 key fix 2 R0 right", 1, params.mRightKeys); + assertEquals("3 key fix 2 R0 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 2 R0 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 2 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("3 key fix 2 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("3 key fix 2 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] [4] ___| + // [1] <2> ___| + public void testLayout4KeyFix2R1() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_R1); + assertEquals("3 key fix 2 R1 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R1 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R1 left", 1, params.mLeftKeys); + assertEquals("3 key fix 2 R1 right", 1, params.mRightKeys); + assertEquals("3 key fix 2 R1 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 2 R1 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 2 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("3 key fix 2 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("3 key fix 2 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] [4] ___| + // <1> [2] ___| + public void testLayout4KeyFix2R2() { + MoreKeysKeyboardParams params = createParams(4, 2, XPOS_R2); + assertEquals("3 key fix 2 R2 columns", 2, params.mNumColumns); + assertEquals("3 key fix 2 R2 rows", 2, params.mNumRows); + assertEquals("3 key fix 2 R2 left", 0, params.mLeftKeys); + assertEquals("3 key fix 2 R2 right", 2, params.mRightKeys); + assertEquals("3 key fix 2 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 2 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 2 R2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key fix 2 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("3 key fix 2 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 2 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [1] <2> [3] + public void testLayout3KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_M0); + assertEquals("3 key fix 5 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 left", 1, params.mLeftKeys); + assertEquals("3 key fix 5 right", 2, params.mRightKeys); + assertEquals("3 key fix 5 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 5 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 5 [3]", 1, params.getColumnPos(2)); + assertEquals("3 key fix 5 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] + public void testLayout3KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L0); + assertEquals("3 key fix 5 L0 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 L0 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("3 key fix 5 L0 right", 3, params.mRightKeys); + assertEquals("3 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("3 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] + public void testLayout3KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L1); + assertEquals("3 key fix 5 L1 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 L1 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("3 key fix 5 L1 right", 3, params.mRightKeys); + assertEquals("3 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("3 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [1] <2> [3] + public void testLayout3KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L2); + assertEquals("3 key fix 5 L2 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 L2 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("3 key fix 5 L2 right", 2, params.mRightKeys); + assertEquals("3 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("3 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [1] [2] <3>| + public void testLayout3KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R0); + assertEquals("3 key fix 5 R0 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 R0 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 R0 left", 2, params.mLeftKeys); + assertEquals("3 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("3 key fix 5 R0 [1]", -2, params.getColumnPos(0)); + assertEquals("3 key fix 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key fix 5 R0 <3>", 0, params.getColumnPos(2)); + assertEquals("3 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [1] [2] <3> ___| + public void testLayout3KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R1); + assertEquals("3 key fix 5 R1 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 R1 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 R1 left", 2, params.mLeftKeys); + assertEquals("3 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("3 key fix 5 R1 [1]", -2, params.getColumnPos(0)); + assertEquals("3 key fix 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key fix 5 R1 <3>", 0, params.getColumnPos(2)); + assertEquals("3 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [1] <2> [3] ___| + public void testLayout3KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R2); + assertEquals("3 key fix 5 R2 columns", 3, params.mNumColumns); + assertEquals("3 key fix 5 R2 rows", 1, params.mNumRows); + assertEquals("3 key fix 5 R2 left", 1, params.mLeftKeys); + assertEquals("3 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("3 key fix 5 R2 [1]", -1, params.getColumnPos(0)); + assertEquals("3 key fix 5 R2 <2>", 0, params.getColumnPos(1)); + assertEquals("3 key fix 5 R2 [3]", 1, params.getColumnPos(2)); + assertEquals("3 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key fix 5 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] + // [1] <2> [3] + public void testLayout4KeyFix3M0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_M0); + assertEquals("4 key fix 3 M0 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 M0 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 M0 left", 1, params.mLeftKeys); + assertEquals("4 key fix 3 M0 right", 2, params.mRightKeys); + assertEquals("4 key fix 3 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("4 key fix 3 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("4 key fix 3 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("4 key fix 3 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] + // |<1> [2] [3] + public void testLayout4KeyFix3L0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L0); + assertEquals("4 key fix 3 L0 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 L0 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 L0 left", 0, params.mLeftKeys); + assertEquals("4 key fix 3 L0 right", 3, params.mRightKeys); + assertEquals("4 key fix 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key fix 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key fix 3 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key fix 3 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] + // |___ <1> [2] [3] + public void testLayout4KeyFix3L1() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L1); + assertEquals("4 key fix 3 L1 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 L1 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 L1 left", 0, params.mLeftKeys); + assertEquals("4 key fix 3 L1 right", 3, params.mRightKeys); + assertEquals("4 key fix 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key fix 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key fix 3 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key fix 3 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ [4] + // |___ ___ [1] <2> [3] + public void testLayout4KeyFix3L2() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L2); + assertEquals("4 key fix 3 L2 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 L2 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 L2 left", 1, params.mLeftKeys); + assertEquals("4 key fix 3 L2 right", 2, params.mRightKeys); + assertEquals("4 key fix 3 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("4 key fix 3 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("4 key fix 3 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("4 key fix 3 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4]| + // [1] [2] <3>| + public void testLayout4KeyFix3R0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R0); + assertEquals("4 key fix 3 R0 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 R0 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 R0 left", 2, params.mLeftKeys); + assertEquals("4 key fix 3 R0 right", 1, params.mRightKeys); + assertEquals("4 key fix 3 R0 [1]", -2, params.getColumnPos(0)); + assertEquals("4 key fix 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key fix 3 R0 <3>", 0, params.getColumnPos(2)); + assertEquals("4 key fix 3 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] ___| + // [1] [2] <3> ___| + public void testLayout4KeyFix3R1() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R1); + assertEquals("4 key fix 3 R1 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 R1 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 R1 left", 2, params.mLeftKeys); + assertEquals("4 key fix 3 R1 right", 1, params.mRightKeys); + assertEquals("4 key fix 3 R1 [1]", -2, params.getColumnPos(0)); + assertEquals("4 key fix 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key fix 3 R1 <3>", 0, params.getColumnPos(2)); + assertEquals("4 key fix 3 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] ___| + // [1] <2> [3] ___| + public void testLayout4KeyFix3R2() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R2); + assertEquals("4 key fix 3 R2 columns", 3, params.mNumColumns); + assertEquals("4 key fix 3 R2 rows", 2, params.mNumRows); + assertEquals("4 key fix 3 R2 left", 1, params.mLeftKeys); + assertEquals("4 key fix 3 R2 right", 2, params.mRightKeys); + assertEquals("4 key fix 3 R2 [1]", -1, params.getColumnPos(0)); + assertEquals("4 key fix 3 R2 <2>", 0, params.getColumnPos(1)); + assertEquals("4 key fix 3 R2 [3]", 1, params.getColumnPos(2)); + assertEquals("4 key fix 3 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("4 key fix 3 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [5] + // [1] <2> [3] + public void testLayout5KeyFix3M0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_M0); + assertEquals("5 key fix 3 M0 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 M0 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 M0 left", 1, params.mLeftKeys); + assertEquals("5 key fix 3 M0 right", 2, params.mRightKeys); + assertEquals("5 key fix 3 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 3 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 3 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 3 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 3 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 3 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key fix 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] + // |<1> [2] [3] + public void testLayout5KeyFix3L0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L0); + assertEquals("5 key fix 3 L0 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 L0 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 L0 left", 0, params.mLeftKeys); + assertEquals("5 key fix 3 L0 right", 3, params.mRightKeys); + assertEquals("5 key fix 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 3 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 3 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 3 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ <1> [2] [3] + public void testLayout5KeyFix3L1() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L1); + assertEquals("5 key fix 3 L1 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 L1 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 L1 left", 0, params.mLeftKeys); + assertEquals("5 key fix 3 L1 right", 3, params.mRightKeys); + assertEquals("5 key fix 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 3 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 3 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 3 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ [1] <2> [3] + public void testLayout5KeyFix3L2() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L2); + assertEquals("5 key fix 3 L2 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 L2 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 L2 left", 1, params.mLeftKeys); + assertEquals("5 key fix 3 L2 right", 2, params.mRightKeys); + assertEquals("5 key fix 3 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 3 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 3 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 3 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 3 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 3 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key fix 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [5]| + // [1] [2] <3>| + public void testLayout5KeyFix3R0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R0); + assertEquals("5 key fix 3 R0 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 R0 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 R0 left", 2, params.mLeftKeys); + assertEquals("5 key fix 3 R0 right", 1, params.mRightKeys); + assertEquals("5 key fix 3 R0 [1]", -2, params.getColumnPos(0)); + assertEquals("5 key fix 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key fix 3 R0 <3>", 0, params.getColumnPos(2)); + assertEquals("5 key fix 3 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("5 key fix 3 R0 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] ___| + // [1] [2] <3> ___| + public void testLayout5KeyFix3R1() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R1); + assertEquals("5 key fix 3 R1 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 R1 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 R1 left", 2, params.mLeftKeys); + assertEquals("5 key fix 3 R1 right", 1, params.mRightKeys); + assertEquals("5 key fix 3 R1 [1]", -2, params.getColumnPos(0)); + assertEquals("5 key fix 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key fix 3 R1 <3>", 0, params.getColumnPos(2)); + assertEquals("5 key fix 3 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("5 key fix 3 R1 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] ___| + // [1] <2> [3] ___| + public void testLayout5KeyFix3R2() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R2); + assertEquals("5 key fix 3 R2 columns", 3, params.mNumColumns); + assertEquals("5 key fix 3 R2 rows", 2, params.mNumRows); + assertEquals("5 key fix 3 R2 left", 1, params.mLeftKeys); + assertEquals("5 key fix 3 R2 right", 2, params.mRightKeys); + assertEquals("5 key fix 3 R2 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 3 R2 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 3 R2 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 3 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 3 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 3 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key fix 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [5] [6] + // [1] <2> [3] + public void testLayout6KeyFix3M0() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_M0); + assertEquals("6 key fix 3 M0 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 M0 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 M0 left", 1, params.mLeftKeys); + assertEquals("6 key fix 3 M0 right", 2, params.mRightKeys); + assertEquals("6 key fix 3 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 3 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 3 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 3 M0 [4]", -1, params.getColumnPos(3)); + assertEquals("6 key fix 3 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 3 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 3 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] [6] + // |<1> [2] [3] + public void testLayout6KeyFix3L0() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_L0); + assertEquals("6 key fix 3 L0 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 L0 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 L0 left", 0, params.mLeftKeys); + assertEquals("6 key fix 3 L0 right", 3, params.mRightKeys); + assertEquals("6 key fix 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 3 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 3 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key fix 3 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key fix 3 L0 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key fix 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] [6] + // |___ <1> [2] [3] + public void testLayout6KeyFix3L1() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_L1); + assertEquals("6 key fix 3 L1 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 L1 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 L1 left", 0, params.mLeftKeys); + assertEquals("6 key fix 3 L1 right", 3, params.mRightKeys); + assertEquals("6 key fix 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 3 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 3 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key fix 3 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key fix 3 L1 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key fix 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] [6] + // |___ [1] <2> [3] + public void testLayout6KeyFix3L2() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_L2); + assertEquals("6 key fix 3 L2 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 L2 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 L2 left", 1, params.mLeftKeys); + assertEquals("6 key fix 3 L2 right", 2, params.mRightKeys); + assertEquals("6 key fix 3 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 3 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 3 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 3 L2 [4]", -1, params.getColumnPos(3)); + assertEquals("6 key fix 3 L2 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 3 L2 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 3 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [5] [6]| + // [1] [2] <3>| + public void testLayout6KeyFix3R0() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_R0); + assertEquals("6 key fix 3 R0 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 R0 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 R0 left", 2, params.mLeftKeys); + assertEquals("6 key fix 3 R0 right", 1, params.mRightKeys); + assertEquals("6 key fix 3 R0 [1]", -2, params.getColumnPos(0)); + assertEquals("6 key fix 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key fix 3 R0 <3>", 0, params.getColumnPos(2)); + assertEquals("6 key fix 3 R0 [4]", -2, params.getColumnPos(3)); + assertEquals("6 key fix 3 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key fix 3 R0 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] [6] ___| + // [1] [2] <3> ___| + public void testLayout6KeyFix3R1() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_R1); + assertEquals("6 key fix 3 R1 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 R1 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 R1 left", 2, params.mLeftKeys); + assertEquals("6 key fix 3 R1 right", 1, params.mRightKeys); + assertEquals("6 key fix 3 R1 [1]", -2, params.getColumnPos(0)); + assertEquals("6 key fix 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key fix 3 R1 <3>", 0, params.getColumnPos(2)); + assertEquals("6 key fix 3 R1 [4]", -2, params.getColumnPos(3)); + assertEquals("6 key fix 3 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key fix 3 R1 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] [6] ___| + // [1] <2> [3] ___| + public void testLayout6KeyFix3R2() { + MoreKeysKeyboardParams params = createParams(6, 3, XPOS_R2); + assertEquals("6 key fix 3 R2 columns", 3, params.mNumColumns); + assertEquals("6 key fix 3 R2 rows", 2, params.mNumRows); + assertEquals("6 key fix 3 R2 left", 1, params.mLeftKeys); + assertEquals("6 key fix 3 R2 right", 2, params.mRightKeys); + assertEquals("6 key fix 3 R2 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 3 R2 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 3 R2 [1]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 3 R2 [4]", -1, params.getColumnPos(3)); + assertEquals("6 key fix 3 R2 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 3 R2 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 3 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // <1> [2] [3] [4] + public void testLayout4KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_M0); + assertEquals("4 key fix 5 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 left", 1, params.mLeftKeys); + assertEquals("4 key fix 5 right", 3, params.mRightKeys); + assertEquals("4 key fix 5 <1>", -1, params.getColumnPos(0)); + assertEquals("4 key fix 5 [2]", 0, params.getColumnPos(1)); + assertEquals("4 key fix 5 [3]", 1, params.getColumnPos(2)); + assertEquals("4 key fix 5 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key fix 5 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] + public void testLayout4KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L0); + assertEquals("4 key fix 5 L0 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 L0 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("4 key fix 5 L0 right", 4, params.mRightKeys); + assertEquals("4 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] + public void testLayout4KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L1); + assertEquals("4 key fix 5 L1 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 L1 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("4 key fix 5 L1 right", 4, params.mRightKeys); + assertEquals("4 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [1] <2> [3] [4] + public void testLayout4KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L2); + assertEquals("4 key fix 5 L2 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 L2 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("4 key fix 5 L2 right", 3, params.mRightKeys); + assertEquals("4 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("4 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("4 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("4 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] <4>| + public void testLayout4KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R0); + assertEquals("4 key fix 5 R0 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 R0 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 R0 left", 3, params.mLeftKeys); + assertEquals("4 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("4 key fix 5 R0 [1]", -3, params.getColumnPos(0)); + assertEquals("4 key fix 5 R0 [2]", -2, params.getColumnPos(1)); + assertEquals("4 key fix 5 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key fix 5 R0 <4>", 0, params.getColumnPos(3)); + assertEquals("4 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] <4> ___| + public void testLayout4KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R1); + assertEquals("4 key fix 5 R1 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 R1 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 R1 left", 3, params.mLeftKeys); + assertEquals("4 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("4 key fix 5 R1 [1]", -3, params.getColumnPos(0)); + assertEquals("4 key fix 5 R1 [2]", -2, params.getColumnPos(1)); + assertEquals("4 key fix 5 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key fix 5 R1 <4>", 0, params.getColumnPos(3)); + assertEquals("4 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [1] [2] <3> [4] ___| + public void testLayout4KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R2); + assertEquals("4 key fix 5 R2 columns", 4, params.mNumColumns); + assertEquals("4 key fix 5 R2 rows", 1, params.mNumRows); + assertEquals("4 key fix 5 R2 left", 2, params.mLeftKeys); + assertEquals("4 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("4 key fix 5 R2 [1]", -2, params.getColumnPos(0)); + assertEquals("4 key fix 5 R2 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key fix 5 R2 <3>", 0, params.getColumnPos(2)); + assertEquals("4 key fix 5 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key fix 5 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] + // [1] <2> [3] [4] + public void testLayout5KeyFix4M0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_M0); + assertEquals("5 key fix 4 M0 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 M0 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 M0 left", 1, params.mLeftKeys); + assertEquals("5 key fix 4 M0 right", 3, params.mRightKeys); + assertEquals("5 key fix 4 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 4 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 4 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 4 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("5 key fix 4 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] + // |<1> [2] [3] [4] + public void testLayout5KeyFix4L0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L0); + assertEquals("5 key fix 4 L0 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 L0 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 L0 left", 0, params.mLeftKeys); + assertEquals("5 key fix 4 L0 right", 4, params.mRightKeys); + assertEquals("5 key fix 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 4 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key fix 4 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] + // |___ <1> [2] [3] [4] + public void testLayout5KeyFix4L1() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L1); + assertEquals("5 key fix 4 L1 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 L1 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 L1 left", 0, params.mLeftKeys); + assertEquals("5 key fix 4 L1 right", 4, params.mRightKeys); + assertEquals("5 key fix 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 4 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key fix 4 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] + // |___ [1] <2> [3] [4] + public void testLayout5KeyFix4L2() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L2); + assertEquals("5 key fix 4 L2 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 L2 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 L2 left", 1, params.mLeftKeys); + assertEquals("5 key fix 4 L2 right", 3, params.mRightKeys); + assertEquals("5 key fix 4 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 4 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 4 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 4 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("5 key fix 4 L2 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5]| + // [1] [2] [3] <4>| + public void testLayout5KeyFix4R0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R0); + assertEquals("5 key fix 4 R0 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 R0 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 R0 left", 3, params.mLeftKeys); + assertEquals("5 key fix 4 R0 right", 1, params.mRightKeys); + assertEquals("5 key fix 4 R0 [1]", -3, params.getColumnPos(0)); + assertEquals("5 key fix 4 R0 [2]", -2, params.getColumnPos(1)); + assertEquals("5 key fix 4 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key fix 4 R0 <4>", 0, params.getColumnPos(3)); + assertEquals("5 key fix 4 R0 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] ___| + // [1] [2] [3] <4> ___| + public void testLayout5KeyFix4R1() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R1); + assertEquals("5 key fix 4 R1 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 R1 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 R1 left", 3, params.mLeftKeys); + assertEquals("5 key fix 4 R1 right", 1, params.mRightKeys); + assertEquals("5 key fix 4 R1 [1]", -3, params.getColumnPos(0)); + assertEquals("5 key fix 4 R1 [2]", -2, params.getColumnPos(1)); + assertEquals("5 key fix 4 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key fix 4 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key fix 4 R1 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] ___| + // [1] [2] <3> [4] ___| + public void testLayout5KeyFix4R2() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R2); + assertEquals("5 key fix 4 R2 columns", 4, params.mNumColumns); + assertEquals("5 key fix 4 R2 rows", 2, params.mNumRows); + assertEquals("5 key fix 4 R2 left", 2, params.mLeftKeys); + assertEquals("5 key fix 4 R2 right", 2, params.mRightKeys); + assertEquals("5 key fix 4 R2 [1]", -2, params.getColumnPos(0)); + assertEquals("5 key fix 4 R2 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key fix 4 R2 <3>", 0, params.getColumnPos(2)); + assertEquals("5 key fix 4 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("5 key fix 4 R2 [5]", 0, params.getColumnPos(4)); + assertEquals("5 key fix 4 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] [6] + // [1] <2> [3] [4] + public void testLayout6KeyFix4M0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_M0); + assertEquals("6 key fix 4 M0 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 M0 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 M0 left", 1, params.mLeftKeys); + assertEquals("6 key fix 4 M0 right", 3, params.mRightKeys); + assertEquals("6 key fix 4 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 4 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 4 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 4 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("6 key fix 4 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 4 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 4 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("6 key fix 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] [6] + // |<1> [2] [3] [4] + public void testLayout6KeyFix4L0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L0); + assertEquals("6 key fix 4 L0 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 L0 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 L0 left", 0, params.mLeftKeys); + assertEquals("6 key fix 4 L0 right", 4, params.mRightKeys); + assertEquals("6 key fix 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 4 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("6 key fix 4 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 4 L0 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] + // |___ <1> [2] [3] [4] + public void testLayout6KeyFix4L1() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L1); + assertEquals("6 key fix 4 L1 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 L1 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 L1 left", 0, params.mLeftKeys); + assertEquals("6 key fix 4 L1 right", 4, params.mRightKeys); + assertEquals("6 key fix 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 4 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("6 key fix 4 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 4 L1 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] + // |___ [1] <2> [3] [4] + public void testLayout6KeyFix4L2() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L2); + assertEquals("6 key fix 4 L2 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 L2 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 L2 left", 1, params.mLeftKeys); + assertEquals("6 key fix 4 L2 right", 3, params.mRightKeys); + assertEquals("6 key fix 4 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 4 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 4 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 4 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("6 key fix 4 L2 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 4 L2 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 4 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("6 key fix 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [6]| + // [1] [2] [3] <4>| + public void testLayout6KeyFix4R0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R0); + assertEquals("6 key fix 4 R0 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 R0 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 R0 left", 3, params.mLeftKeys); + assertEquals("6 key fix 4 R0 right", 1, params.mRightKeys); + assertEquals("6 key fix 4 R0 [1]", -3, params.getColumnPos(0)); + assertEquals("6 key fix 4 R0 [2]", -2, params.getColumnPos(1)); + assertEquals("6 key fix 4 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key fix 4 R0 <4>", 0, params.getColumnPos(3)); + assertEquals("6 key fix 4 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key fix 4 R0 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] ___| + // [1] [2] [3] <4> ___| + public void testLayout6KeyFix4R1() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R1); + assertEquals("6 key fix 4 R1 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 R1 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 R1 left", 3, params.mLeftKeys); + assertEquals("6 key fix 4 R1 right", 1, params.mRightKeys); + assertEquals("6 key fix 4 R1 [1]", -3, params.getColumnPos(0)); + assertEquals("6 key fix 4 R1 [2]", -2, params.getColumnPos(1)); + assertEquals("6 key fix 4 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key fix 4 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key fix 4 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key fix 4 R1 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] ___| + // [1] [2] <3> [4] ___| + public void testLayout6KeyFix4R2() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R2); + assertEquals("6 key fix 4 R2 columns", 4, params.mNumColumns); + assertEquals("6 key fix 4 R2 rows", 2, params.mNumRows); + assertEquals("6 key fix 4 R2 left", 2, params.mLeftKeys); + assertEquals("6 key fix 4 R2 right", 2, params.mRightKeys); + assertEquals("6 key fix 4 R2 [1]", -2, params.getColumnPos(0)); + assertEquals("6 key fix 4 R2 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key fix 4 R2 <3>", 0, params.getColumnPos(2)); + assertEquals("6 key fix 4 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("6 key fix 4 R2 [5]", 0, params.getColumnPos(4)); + assertEquals("6 key fix 4 R2 [6]", 1, params.getColumnPos(5)); + assertEquals("6 key fix 4 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("6 key fix 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] + // [1] <2> [3] [4] + public void testLayout7KeyFix4M0() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_M0); + assertEquals("7 key fix 4 M0 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 M0 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 M0 left", 1, params.mLeftKeys); + assertEquals("7 key fix 4 M0 right", 3, params.mRightKeys); + assertEquals("7 key fix 4 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("7 key fix 4 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("7 key fix 4 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("7 key fix 4 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key fix 4 M0 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key fix 4 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 4 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 4 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] [6] [7] + // |<1> [2] [3] [4] + public void testLayout7KeyFix4L0() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_L0); + assertEquals("7 key fix 4 L0 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 L0 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 L0 left", 0, params.mLeftKeys); + assertEquals("7 key fix 4 L0 right", 4, params.mRightKeys); + assertEquals("7 key fix 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 4 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 4 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key fix 4 L0 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key fix 4 L0 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key fix 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] + // |___ <1> [2] [3] [4] + public void testLayout7KeyFix4L1() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_L1); + assertEquals("7 key fix 4 L1 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 L1 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 L1 left", 0, params.mLeftKeys); + assertEquals("7 key fix 4 L1 right", 4, params.mRightKeys); + assertEquals("7 key fix 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 4 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 4 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key fix 4 L1 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key fix 4 l1 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key fix 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] + // |___ [1] <2> [3] [4] + public void testLayout7KeyFix4L2() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_L2); + assertEquals("7 key fix 4 L2 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 L2 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 L2 left", 1, params.mLeftKeys); + assertEquals("7 key fix 4 L2 right", 3, params.mRightKeys); + assertEquals("7 key fix 4 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("7 key fix 4 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("7 key fix 4 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("7 key fix 4 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key fix 4 L2 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key fix 4 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 4 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 4 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7]| + // [1] [2] [3] <4>| + public void testLayout7KeyFix4R0() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_R0); + assertEquals("7 key fix 4 R0 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 R0 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 R0 left", 3, params.mLeftKeys); + assertEquals("7 key fix 4 R0 right", 1, params.mRightKeys); + assertEquals("7 key fix 4 R0 [1]", -3, params.getColumnPos(0)); + assertEquals("7 key fix 4 R0 [2]", -2, params.getColumnPos(1)); + assertEquals("7 key fix 4 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key fix 4 R0 <4>", 0, params.getColumnPos(3)); + assertEquals("7 key fix 4 R0 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key fix 4 R0 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 4 R0 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key fix 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] ___| + // [1] [2] [3] <4> ___| + public void testLayout7KeyFix4R1() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_R1); + assertEquals("7 key fix 4 R1 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 R1 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 R1 left", 3, params.mLeftKeys); + assertEquals("7 key fix 4 R1 right", 1, params.mRightKeys); + assertEquals("7 key fix 4 R1 [1]", -3, params.getColumnPos(0)); + assertEquals("7 key fix 4 R1 [2]", -2, params.getColumnPos(1)); + assertEquals("7 key fix 4 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key fix 4 R1 <4>", 0, params.getColumnPos(3)); + assertEquals("7 key fix 4 R1 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key fix 4 R1 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 4 R1 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key fix 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] ___| + // [1] [2] <3> [4] ___| + public void testLayout7KeyFix4R2() { + MoreKeysKeyboardParams params = createParams(7, 4, XPOS_R2); + assertEquals("7 key fix 4 R2 columns", 4, params.mNumColumns); + assertEquals("7 key fix 4 R2 rows", 2, params.mNumRows); + assertEquals("7 key fix 4 R2 left", 2, params.mLeftKeys); + assertEquals("7 key fix 4 R2 right", 2, params.mRightKeys); + assertEquals("7 key fix 4 R2 [1]", -2, params.getColumnPos(0)); + assertEquals("7 key fix 4 R2 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key fix 4 R2 <3>", 0, params.getColumnPos(2)); + assertEquals("7 key fix 4 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("7 key fix 4 R2 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key fix 4 R2 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 4 R2 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 4 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] [8] + // [1] <2> [3] [4] + public void testLayout8KeyFix4M0() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_M0); + assertEquals("8 key fix 4 M0 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 M0 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 M0 left", 1, params.mLeftKeys); + assertEquals("8 key fix 4 M0 right", 3, params.mRightKeys); + assertEquals("8 key fix 4 M0 [1]", -1, params.getColumnPos(0)); + assertEquals("8 key fix 4 M0 <2>", 0, params.getColumnPos(1)); + assertEquals("8 key fix 4 M0 [3]", 1, params.getColumnPos(2)); + assertEquals("8 key fix 4 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("8 key fix 4 M0 [5]", -1, params.getColumnPos(4)); + assertEquals("8 key fix 4 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("8 key fix 4 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("8 key fix 4 M0 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key fix 4 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] [6] [7] [8] + // |<1> [2] [3] [4] + public void testLayout8KeyFix4L0() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_L0); + assertEquals("8 key fix 4 L0 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 L0 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 L0 left", 0, params.mLeftKeys); + assertEquals("8 key fix 4 L0 right", 4, params.mRightKeys); + assertEquals("8 key fix 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key fix 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key fix 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key fix 4 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key fix 4 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key fix 4 L0 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key fix 4 L0 [7]", 2, params.getColumnPos(6)); + assertEquals("8 key fix 4 L0 [8]", 3, params.getColumnPos(7)); + assertEquals("8 key fix 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] [8] + // |___ <1> [2] [3] [4] + public void testLayout8KeyFix4L1() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_L1); + assertEquals("8 key fix 4 L1 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 L1 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 L1 left", 0, params.mLeftKeys); + assertEquals("8 key fix 4 L1 right", 4, params.mRightKeys); + assertEquals("8 key fix 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key fix 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key fix 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key fix 4 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key fix 4 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key fix 4 L1 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key fix 4 L1 [7]", 2, params.getColumnPos(6)); + assertEquals("8 key fix 4 L1 [8]", 3, params.getColumnPos(7)); + assertEquals("8 key fix 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] [8] + // |___ [1] <2> [3] [4] + public void testLayout8KeyFix4L2() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_L2); + assertEquals("8 key fix 4 L2 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 L2 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 L2 left", 1, params.mLeftKeys); + assertEquals("8 key fix 4 L2 right", 3, params.mRightKeys); + assertEquals("8 key fix 4 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("8 key fix 4 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("8 key fix 4 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("8 key fix 4 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("8 key fix 4 L2 [5]", -1, params.getColumnPos(4)); + assertEquals("8 key fix 4 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("8 key fix 4 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("8 key fix 4 L2 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key fix 4 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] [8]| + // [1] [2] [3] <4>| + public void testLayout8KeyFix4R0() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_R0); + assertEquals("8 key fix 4 R0 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 R0 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 R0 left", 3, params.mLeftKeys); + assertEquals("8 key fix 4 R0 right", 1, params.mRightKeys); + assertEquals("8 key fix 4 R0 [1]", -3, params.getColumnPos(0)); + assertEquals("8 key fix 4 R0 [2]", -2, params.getColumnPos(1)); + assertEquals("8 key fix 4 R0 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key fix 4 R0 <4>", 0, params.getColumnPos(3)); + assertEquals("8 key fix 4 R0 [5]", -3, params.getColumnPos(4)); + assertEquals("8 key fix 4 R0 [6]", -2, params.getColumnPos(5)); + assertEquals("8 key fix 4 R0 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key fix 4 R0 [8]", 0, params.getColumnPos(7)); + assertEquals("8 key fix 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] [8] ___| + // [1] [2] [3] <4> ___| + public void testLayout8KeyFix4R1() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_R1); + assertEquals("8 key fix 4 R1 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 R1 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 R1 left", 3, params.mLeftKeys); + assertEquals("8 key fix 4 R1 right", 1, params.mRightKeys); + assertEquals("8 key fix 4 R1 [1]", -3, params.getColumnPos(0)); + assertEquals("8 key fix 4 R1 [2]", -2, params.getColumnPos(1)); + assertEquals("8 key fix 4 R1 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key fix 4 R1 <4>", 0, params.getColumnPos(3)); + assertEquals("8 key fix 4 R1 [5]", -3, params.getColumnPos(4)); + assertEquals("8 key fix 4 R1 [6]", -2, params.getColumnPos(5)); + assertEquals("8 key fix 4 R1 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key fix 4 R1 [8]", 0, params.getColumnPos(7)); + assertEquals("8 key fix 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] [8] ___| + // [1] [2] <3> [4] ___| + public void testLayout8KeyFix4R2() { + MoreKeysKeyboardParams params = createParams(8, 4, XPOS_R2); + assertEquals("8 key fix 4 R2 columns", 4, params.mNumColumns); + assertEquals("8 key fix 4 R2 rows", 2, params.mNumRows); + assertEquals("8 key fix 4 R2 left", 2, params.mLeftKeys); + assertEquals("8 key fix 4 R2 right", 2, params.mRightKeys); + assertEquals("8 key fix 4 R2 [1]", -2, params.getColumnPos(0)); + assertEquals("8 key fix 4 R2 [2]", -1, params.getColumnPos(1)); + assertEquals("8 key fix 4 R2 <3>", 0, params.getColumnPos(2)); + assertEquals("8 key fix 4 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("8 key fix 4 R2 [5]", -2, params.getColumnPos(4)); + assertEquals("8 key fix 4 R2 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key fix 4 R2 [7]", 0, params.getColumnPos(6)); + assertEquals("8 key fix 4 R2 [8]", 1, params.getColumnPos(7)); + assertEquals("8 key fix 4 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [1] [2] <3> [4] [5] + public void testLayout5KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_M0); + assertEquals("5 key fix 5 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 left", 2, params.mLeftKeys); + assertEquals("5 key fix 5 right", 3, params.mRightKeys); + assertEquals("5 key fix 5 [1]", -2, params.getColumnPos(0)); + assertEquals("5 key fix 5 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key fix 5 <3>", 0, params.getColumnPos(2)); + assertEquals("5 key fix 5 [4]", 1, params.getColumnPos(3)); + assertEquals("5 key fix 5 [5]", 2, params.getColumnPos(4)); + assertEquals("5 key fix 5 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] [5] + public void testLayout5KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L0); + assertEquals("5 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 L0 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("5 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("5 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("5 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] [5] + public void testLayout5KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L1); + assertEquals("5 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 L1 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("5 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("5 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("5 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [1] <2> [3] [4] [5] + public void testLayout5KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L2); + assertEquals("5 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 L2 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("5 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("5 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("5 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("5 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("5 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("5 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("5 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] <5>| + public void testLayout5KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R0); + assertEquals("5 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 R0 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("5 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("5 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("5 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("5 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("5 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("5 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] <5> ___| + public void testLayout5KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R1); + assertEquals("5 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 R1 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("5 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("5 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("5 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("5 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("5 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("5 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] <4> [5] ___| + public void testLayout5KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R2); + assertEquals("5 key fix 5 R2 columns", 5, params.mNumColumns); + assertEquals("5 key fix 5 R2 rows", 1, params.mNumRows); + assertEquals("5 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("5 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("5 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("5 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("5 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("5 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] + // [1] [2] <3> [4] [5] + public void testLayout6KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_M0); + assertEquals("6 key fix 5 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 left", 2, params.mLeftKeys); + assertEquals("6 key fix 5 right", 3, params.mRightKeys); + assertEquals("6 key fix 5 [1]", -2, params.getColumnPos(0)); + assertEquals("6 key fix 5 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key fix 5 <3>", 0, params.getColumnPos(2)); + assertEquals("6 key fix 5 [4]", 1, params.getColumnPos(3)); + assertEquals("6 key fix 5 [5]", 2, params.getColumnPos(4)); + assertEquals("6 key fix 5 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] + // |<1> [2] [3] [4] [5] + public void testLayout6KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L0); + assertEquals("6 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 L0 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("6 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("6 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("6 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("6 key fix 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] + // |___ <1> [2] [3] [4] [5] + public void testLayout6KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L1); + assertEquals("6 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 L1 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("6 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("6 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("6 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("6 key fix 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] + // |___ [1] <2> [3] [4] [5] + public void testLayout6KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L2); + assertEquals("6 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 L2 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("6 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("6 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("6 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("6 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("6 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("6 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("6 key fix 5 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6]| + // [1] [2] [3] [4] <5>| + public void testLayout6KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R0); + assertEquals("6 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 R0 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("6 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("6 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("6 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("6 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("6 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("6 key fix 5 R0 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] ___| + // [1] [2] [3] [4] <5> ___| + public void testLayout6KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R1); + assertEquals("6 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 R1 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("6 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("6 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("6 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("6 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("6 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("6 key fix 5 R1 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] ___| + // [1] [2] [3] <4> [5] ___| + public void testLayout6KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R2); + assertEquals("6 key fix 5 R2 columns", 5, params.mNumColumns); + assertEquals("6 key fix 5 R2 rows", 2, params.mNumRows); + assertEquals("6 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("6 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("6 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("6 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("6 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("6 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key fix 5 R2 [6]", 0, params.getColumnPos(5)); + assertEquals("6 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] [7] + // [1] [2] <3> [4] [5] + public void testLayout7KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_M0); + assertEquals("7 key fix 5 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 left", 2, params.mLeftKeys); + assertEquals("7 key fix 5 right", 3, params.mRightKeys); + assertEquals("7 key fix 5 [1]", -2, params.getColumnPos(0)); + assertEquals("7 key fix 5 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key fix 5 <3>", 0, params.getColumnPos(2)); + assertEquals("7 key fix 5 [4]", 1, params.getColumnPos(3)); + assertEquals("7 key fix 5 [5]", 2, params.getColumnPos(4)); + assertEquals("7 key fix 5 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 5 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 5 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key fix 5 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] + // |<1> [2] [3] [4] [5] + public void testLayout7KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L0); + assertEquals("7 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 L0 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("7 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("7 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key fix 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] + // |___ <1> [2] [3] [4] [5] + public void testLayout7KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L1); + assertEquals("7 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 L1 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("7 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("7 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key fix 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] + // |___ [1] <2> [3] [4] [5] + public void testLayout7KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L2); + assertEquals("7 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 L2 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("7 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("7 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("7 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("7 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("7 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("7 key fix 5 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 5 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 5 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [7]| + // [1] [2] [3] [4] <5>| + public void testLayout7KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R0); + assertEquals("7 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 R0 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("7 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("7 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("7 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("7 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("7 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("7 key fix 5 R0 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 5 R0 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] ___| + // [1] [2] [3] [4] <5> ___| + public void testLayout7KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R1); + assertEquals("7 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("7 key fix 5 R1 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("7 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("7 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("7 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("7 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("7 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("7 key fix 5 R1 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 5 R1 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] ___| + // [1] [2] [3] <4> [5] ___| + public void testLayout7KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R2); + assertEquals("7 key fix 5 R2 columns",5, params.mNumColumns); + assertEquals("7 key fix 5 R2 rows", 2, params.mNumRows); + assertEquals("7 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("7 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("7 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("7 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("7 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("7 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key fix 5 R2 [6]", 0, params.getColumnPos(5)); + assertEquals("7 key fix 5 R2 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 5 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] + // [1] [2] <3> [4] [5] + public void testLayout8KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_M0); + assertEquals("8 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 M0 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("8 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("8 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("8 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("8 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("8 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("8 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("8 key fix 5 M0 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key fix 5 M0 [7]", 0, params.getColumnPos(6)); + assertEquals("8 key fix 5 M0 [8]", 1, params.getColumnPos(7)); + assertEquals("8 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] [8] + // |<1> [2] [3] [4] [5] + public void testLayout8KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L0); + assertEquals("8 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 L0 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("8 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("8 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("8 key fix 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("8 key fix 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("8 key fix 5 L0 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] + // |___ <1> [2] [3] [4] [5] + public void testLayout8KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L1); + assertEquals("8 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 L1 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("8 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("8 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("8 key fix 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("8 key fix 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("8 key fix 5 L1 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] + // |___ [1] <2> [3] [4] [5] + public void testLayout8KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L2); + assertEquals("8 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 L2 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("8 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("8 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("8 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("8 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("8 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("8 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("8 key fix 5 L2 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key fix 5 L2 [7]", 0, params.getColumnPos(6)); + assertEquals("8 key fix 5 L2 [8]", 1, params.getColumnPos(7)); + assertEquals("8 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8]| + // [1] [2] [3] [4] <5>| + public void testLayout8KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R0); + assertEquals("8 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 R0 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("8 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("8 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("8 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("8 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("8 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("8 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("8 key fix 5 R0 [6]", -2, params.getColumnPos(5)); + assertEquals("8 key fix 5 R0 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key fix 5 R0 [8]", 0, params.getColumnPos(7)); + assertEquals("8 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] ___| + // [1] [2] [3] [4] <5> ___| + public void testLayout8KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R1); + assertEquals("8 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 R1 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("8 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("8 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("8 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("8 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("8 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("8 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("8 key fix 5 R1 [6]", -2, params.getColumnPos(5)); + assertEquals("8 key fix 5 R1 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key fix 5 R1 [8]", 0, params.getColumnPos(7)); + assertEquals("8 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] ___| + // [1] [2] [3] <4> [5] ___| + public void testLayout8KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R2); + assertEquals("8 key fix 5 R2 columns", 5, params.mNumColumns); + assertEquals("8 key fix 5 R2 rows", 2, params.mNumRows); + assertEquals("8 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("8 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("8 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("8 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("8 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("8 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("8 key fix 5 R2 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key fix 5 R2 [7]", 0, params.getColumnPos(6)); + assertEquals("8 key fix 5 R2 [8]", 1, params.getColumnPos(7)); + assertEquals("8 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] + // [1] [2] <3> [4] [5] + public void testLayout9KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_M0); + assertEquals("9 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 M0 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("9 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("9 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("9 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("9 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("9 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("9 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("9 key fix 5 M0 [6]", -1, params.getColumnPos(5)); + assertEquals("9 key fix 5 M0 [7]", 0, params.getColumnPos(6)); + assertEquals("9 key fix 5 M0 [8]", 1, params.getColumnPos(7)); + assertEquals("9 key fix 5 M0 [9]", 2, params.getColumnPos(8)); + assertEquals("9 key fix 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] [8] [9] + // |<1> [2] [3] [4] [5] + public void testLayout9KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L0); + assertEquals("9 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 L0 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("9 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("9 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("9 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("9 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("9 key fix 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key fix 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key fix 5 L0 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key fix 5 L0 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] + // |___ <1> [2] [3] [4] [5] + public void testLayout9KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L1); + assertEquals("9 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 L1 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("9 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("9 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("9 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("9 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("9 key fix 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key fix 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key fix 5 L1 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key fix 5 L1 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key fix 5 L1 adjust",0, params.mTopRowAdjustment); + assertEquals("9 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] + // |___ [1] <2> [3] [4] [5] + public void testLayout9KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L2); + assertEquals("9 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 L2 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("9 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("9 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("9 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("9 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("9 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("9 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("9 key fix 5 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key fix 5 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key fix 5 L2 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key fix 5 L2 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key fix 5 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9]| + // [1] [2] [3] [4] <5>| + public void testLayout9KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R0); + assertEquals("9 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 R0 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("9 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("9 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("9 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("9 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("9 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("9 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("9 key fix 5 R0 [6]", -3, params.getColumnPos(5)); + assertEquals("9 key fix 5 R0 [7]", -2, params.getColumnPos(6)); + assertEquals("9 key fix 5 R0 [8]", -1, params.getColumnPos(7)); + assertEquals("9 key fix 5 R0 [9]", 0, params.getColumnPos(8)); + assertEquals("9 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] ___| + // [1] [2] [3] [4] <5> ___| + public void testLayout9KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R1); + assertEquals("9 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 R1 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("9 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("9 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("9 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("9 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("9 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("9 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("9 key fix 5 R1 [6]", -3, params.getColumnPos(5)); + assertEquals("9 key fix 5 R1 [7]", -2, params.getColumnPos(6)); + assertEquals("9 key fix 5 R1 [8]", -1, params.getColumnPos(7)); + assertEquals("9 key fix 5 R1 [9]", 0, params.getColumnPos(8)); + assertEquals("9 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] ___| + // [1] [2] [3] <4> [5] ___| + public void testLayout9KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R2); + assertEquals("9 key fix 5 R2 columns", 5, params.mNumColumns); + assertEquals("9 key fix 5 R2 rows", 2, params.mNumRows); + assertEquals("9 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("9 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("9 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("9 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("9 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("9 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("9 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("9 key fix 5 R2 [6]", -2, params.getColumnPos(5)); + assertEquals("9 key fix 5 R2 [7]", -1, params.getColumnPos(6)); + assertEquals("9 key fix 5 R2 [8]", 0, params.getColumnPos(7)); + assertEquals("9 key fix 5 R2 [9]", 1, params.getColumnPos(8)); + assertEquals("9 key fix 5 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] [A] + // [1] [2] <3> [4] [5] + public void testLayout10KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_M0); + assertEquals("10 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 M0 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("10 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("10 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("10 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("10 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("10 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("10 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("10 key fix 5 M0 [6]", -2, params.getColumnPos(5)); + assertEquals("10 key fix 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("10 key fix 5 M0 [8]", 0, params.getColumnPos(7)); + assertEquals("10 key fix 5 M0 [9]", 1, params.getColumnPos(8)); + assertEquals("10 key fix 5 M0 [A]", 2, params.getColumnPos(9)); + assertEquals("10 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] [8] [9] [A] + // |<1> [2] [3] [4] [5] + public void testLayout10KeyFix5L0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L0); + assertEquals("10 key fix 5 L0 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 L0 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 L0 left", 0, params.mLeftKeys); + assertEquals("10 key fix 5 L0 right", 5, params.mRightKeys); + assertEquals("10 key fix 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key fix 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key fix 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("10 key fix 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("10 key fix 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("10 key fix 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key fix 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key fix 5 L0 [8]", 2, params.getColumnPos(7)); + assertEquals("10 key fix 5 L0 [9]", 3, params.getColumnPos(8)); + assertEquals("10 key fix 5 L0 [A]", 4, params.getColumnPos(9)); + assertEquals("10 key fix 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] [A] + // |___ <1> [2] [3] [4] [5] + public void testLayout10KeyFix5L1() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L1); + assertEquals("10 key fix 5 L1 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 L1 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 L1 left", 0, params.mLeftKeys); + assertEquals("10 key fix 5 L1 right", 5, params.mRightKeys); + assertEquals("10 key fix 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key fix 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key fix 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("10 key fix 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("10 key fix 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("10 key fix 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key fix 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key fix 5 L1 [8]", 2, params.getColumnPos(7)); + assertEquals("10 key fix 5 L1 [9]", 3, params.getColumnPos(8)); + assertEquals("10 key fix 5 L1 [A]", 4, params.getColumnPos(9)); + assertEquals("10 key fix 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] [A] + // |___ [1] <2> [3] [4] [5] + public void testLayout10KeyFix5L2() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L2); + assertEquals("10 key fix 5 L2 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 L2 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 L2 left", 1, params.mLeftKeys); + assertEquals("10 key fix 5 L2 right", 4, params.mRightKeys); + assertEquals("10 key fix 5 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("10 key fix 5 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("10 key fix 5 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("10 key fix 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("10 key fix 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("10 key fix 5 L2 [6]", -1, params.getColumnPos(5)); + assertEquals("10 key fix 5 L2 [7]", 0, params.getColumnPos(6)); + assertEquals("10 key fix 5 L2 [8]", 1, params.getColumnPos(7)); + assertEquals("10 key fix 5 L2 [9]", 2, params.getColumnPos(8)); + assertEquals("10 key fix 5 L2 [A]", 3, params.getColumnPos(9)); + assertEquals("10 key fix 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] [A]| + // [1] [2] [3] [4] <5>| + public void testLayout10KeyFix5R0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R0); + assertEquals("10 key fix 5 R0 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 R0 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 R0 left", 4, params.mLeftKeys); + assertEquals("10 key fix 5 R0 right", 1, params.mRightKeys); + assertEquals("10 key fix 5 R0 [1]", -4, params.getColumnPos(0)); + assertEquals("10 key fix 5 R0 [2]", -3, params.getColumnPos(1)); + assertEquals("10 key fix 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("10 key fix 5 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("10 key fix 5 R0 <5>", 0, params.getColumnPos(4)); + assertEquals("10 key fix 5 R0 [6]", -4, params.getColumnPos(5)); + assertEquals("10 key fix 5 R0 [7]", -3, params.getColumnPos(6)); + assertEquals("10 key fix 5 R0 [8]", -2, params.getColumnPos(7)); + assertEquals("10 key fix 5 R0 [9]", -1, params.getColumnPos(8)); + assertEquals("10 key fix 5 R0 [A]", 0, params.getColumnPos(9)); + assertEquals("10 key fix 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] [A] ___| + // [1] [2] [3] [4] <5> ___| + public void testLayout10KeyFix5R1() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R1); + assertEquals("10 key fix 5 R1 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 R1 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 R1 left", 4, params.mLeftKeys); + assertEquals("10 key fix 5 R1 right", 1, params.mRightKeys); + assertEquals("10 key fix 5 R1 [1]", -4, params.getColumnPos(0)); + assertEquals("10 key fix 5 R1 [2]", -3, params.getColumnPos(1)); + assertEquals("10 key fix 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("10 key fix 5 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("10 key fix 5 R1 <5>", 0, params.getColumnPos(4)); + assertEquals("10 key fix 5 R1 [6]", -4, params.getColumnPos(5)); + assertEquals("10 key fix 5 R1 [7]", -3, params.getColumnPos(6)); + assertEquals("10 key fix 5 R1 [8]", -2, params.getColumnPos(7)); + assertEquals("10 key fix 5 R1 [9]", -1, params.getColumnPos(8)); + assertEquals("10 key fix 5 R1 [A]", 0, params.getColumnPos(9)); + assertEquals("10 key fix 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [6] [7] [8] [9] [A] ___| + // [1] [2] [3] <4> [5] ___| + public void testLayout10KeyFix5R2() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R2); + assertEquals("10 key fix 5 R2 columns", 5, params.mNumColumns); + assertEquals("10 key fix 5 R2 rows", 2, params.mNumRows); + assertEquals("10 key fix 5 R2 left", 3, params.mLeftKeys); + assertEquals("10 key fix 5 R2 right", 2, params.mRightKeys); + assertEquals("10 key fix 5 R2 [1]", -3, params.getColumnPos(0)); + assertEquals("10 key fix 5 R2 [2]", -2, params.getColumnPos(1)); + assertEquals("10 key fix 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("10 key fix 5 R2 <4>", 0, params.getColumnPos(3)); + assertEquals("10 key fix 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("10 key fix 5 R2 [6]", -3, params.getColumnPos(5)); + assertEquals("10 key fix 5 R2 [7]", -2, params.getColumnPos(6)); + assertEquals("10 key fix 5 R2 [8]", -1, params.getColumnPos(7)); + assertEquals("10 key fix 5 R2 [9]", 0, params.getColumnPos(8)); + assertEquals("10 key fix 5 R2 [A]", 1, params.getColumnPos(9)); + assertEquals("10 key fix 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key fix 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [B] + // [6] [7] [8] [9] [A] + // [1] [2] <3> [4] [5] + public void testLayout11KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(11, 5, XPOS_M0); + assertEquals("11 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("11 key fix 5 M0 rows", 3, params.mNumRows); + assertEquals("11 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("11 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("11 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("11 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("11 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("11 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("11 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("11 key fix 5 M0 [6]", -2, params.getColumnPos(5)); + assertEquals("11 key fix 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("11 key fix 5 M0 [8]", 0, params.getColumnPos(7)); + assertEquals("11 key fix 5 M0 [9]", 1, params.getColumnPos(8)); + assertEquals("11 key fix 5 M0 [A]", 2, params.getColumnPos(9)); + assertEquals("11 key fix 5 M0 [B]", 0, params.getColumnPos(10)); + assertEquals("11 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("11 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [B] [C] + // [6] [7] [8] [9] [A] + // [1] [2] <3> [4] [5] + public void testLayout12KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(12, 5, XPOS_M0); + assertEquals("12 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("12 key fix 5 M0 rows", 3, params.mNumRows); + assertEquals("12 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("12 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("12 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("12 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("12 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("12 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("12 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("12 key fix 5 M0 [6]", -2, params.getColumnPos(5)); + assertEquals("12 key fix 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("12 key fix 5 M0 [8]", 0, params.getColumnPos(7)); + assertEquals("12 key fix 5 M0 [9]", 1, params.getColumnPos(8)); + assertEquals("12 key fix 5 M0 [A]", 2, params.getColumnPos(9)); + assertEquals("12 key fix 5 M0 [B]", 0, params.getColumnPos(10)); + assertEquals("12 key fix 5 M0 [C]", 1, params.getColumnPos(11)); + assertEquals("12 key fix 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("12 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [B] [C] [D] + // [6] [7] [8] [9] [A] + // [1] [2] <3> [4] [5] + public void testLayout13KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(13, 5, XPOS_M0); + assertEquals("13 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("13 key fix 5 M0 rows", 3, params.mNumRows); + assertEquals("13 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("13 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("13 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("13 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("13 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("13 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("13 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("13 key fix 5 M0 [6]", -2, params.getColumnPos(5)); + assertEquals("13 key fix 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("13 key fix 5 M0 [8]", 0, params.getColumnPos(7)); + assertEquals("13 key fix 5 M0 [9]", 1, params.getColumnPos(8)); + assertEquals("13 key fix 5 M0 [A]", 2, params.getColumnPos(9)); + assertEquals("13 key fix 5 M0 [B]", -1, params.getColumnPos(10)); + assertEquals("13 key fix 5 M0 [C]", 0, params.getColumnPos(11)); + assertEquals("13 key fix 5 M0 [D]", 1, params.getColumnPos(12)); + assertEquals("13 key fix 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("13 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [B] [C] [D] [E] + // [6] [7] [8] [9] [A] + // [1] [2] <3> [4] [5] + public void testLayout14KeyFix5M0() { + MoreKeysKeyboardParams params = createParams(14, 5, XPOS_M0); + assertEquals("14 key fix 5 M0 columns", 5, params.mNumColumns); + assertEquals("14 key fix 5 M0 rows", 3, params.mNumRows); + assertEquals("14 key fix 5 M0 left", 2, params.mLeftKeys); + assertEquals("14 key fix 5 M0 right", 3, params.mRightKeys); + assertEquals("14 key fix 5 M0 [1]", -2, params.getColumnPos(0)); + assertEquals("14 key fix 5 M0 [2]", -1, params.getColumnPos(1)); + assertEquals("14 key fix 5 M0 <3>", 0, params.getColumnPos(2)); + assertEquals("14 key fix 5 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("14 key fix 5 M0 [5]", 2, params.getColumnPos(4)); + assertEquals("14 key fix 5 M0 [6]", -2, params.getColumnPos(5)); + assertEquals("14 key fix 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("14 key fix 5 M0 [8]", 0, params.getColumnPos(7)); + assertEquals("14 key fix 5 M0 [9]", 1, params.getColumnPos(8)); + assertEquals("14 key fix 5 M0 [A]", 2, params.getColumnPos(9)); + assertEquals("14 key fix 5 M0 [B]", -1, params.getColumnPos(10)); + assertEquals("14 key fix 5 M0 [C]", 0, params.getColumnPos(11)); + assertEquals("14 key fix 5 M0 [D]", 1, params.getColumnPos(12)); + assertEquals("14 key fix 5 M0 [E]", 2, params.getColumnPos(13)); + assertEquals("14 key fix 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("14 key fix 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] [5] [6] [7] + public void testLayout7KeyFix7L0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L0); + assertEquals("7 key fix 7 L0 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 L0 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 L0 left", 0, params.mLeftKeys); + assertEquals("7 key fix 7 L0 right", 7, params.mRightKeys); + assertEquals("7 key fix 7 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 7 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 7 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 7 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 7 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key fix 7 L0 [6]", 5, params.getColumnPos(5)); + assertEquals("7 key fix 7 L0 [7]", 6, params.getColumnPos(6)); + assertEquals("7 key fix 7 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] [5] [6] [7] + public void testLayout7KeyFix7L1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L1); + assertEquals("7 key fix 7 L1 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 L1 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 L1 left", 0, params.mLeftKeys); + assertEquals("7 key fix 7 L1 right", 7, params.mRightKeys); + assertEquals("7 key fix 7 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key fix 7 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key fix 7 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key fix 7 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key fix 7 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key fix 7 L1 [6]", 5, params.getColumnPos(5)); + assertEquals("7 key fix 7 L1 [7]", 6, params.getColumnPos(6)); + assertEquals("7 key fix 7 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [1] <2> [3] [4] [5] [6] [7] + public void testLayout7KeyFix7L2() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L2); + assertEquals("7 key fix 7 L2 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 L2 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 L2 left", 1, params.mLeftKeys); + assertEquals("7 key fix 7 L2 right", 6, params.mRightKeys); + assertEquals("7 key fix 7 L2 [1]", -1, params.getColumnPos(0)); + assertEquals("7 key fix 7 L2 <2>", 0, params.getColumnPos(1)); + assertEquals("7 key fix 7 L2 [3]", 1, params.getColumnPos(2)); + assertEquals("7 key fix 7 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key fix 7 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("7 key fix 7 L2 [6]", 4, params.getColumnPos(5)); + assertEquals("7 key fix 7 L2 [7]", 5, params.getColumnPos(6)); + assertEquals("7 key fix 7 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |___ [1] [2] <3> [4] [5] [6] [7] + public void testLayout7KeyFix7L3() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L3); + assertEquals("7 key fix 7 L3 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 L3 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 L3 left", 2, params.mLeftKeys); + assertEquals("7 key fix 7 L3 right", 5, params.mRightKeys); + assertEquals("7 key fix 7 L3 [1]", -2, params.getColumnPos(0)); + assertEquals("7 key fix 7 L3 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key fix 7 L3 <3>", 0, params.getColumnPos(2)); + assertEquals("7 key fix 7 L3 [4]", 1, params.getColumnPos(3)); + assertEquals("7 key fix 7 L3 [5]", 2, params.getColumnPos(4)); + assertEquals("7 key fix 7 L3 [6]", 3, params.getColumnPos(5)); + assertEquals("7 key fix 7 L3 [7]", 4, params.getColumnPos(6)); + assertEquals("7 key fix 7 L3 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 L3 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |___ [1] [2] [3] <4> [5] [6] [7] ___ ___| + public void testLayout7KeyFix7M0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M0); + assertEquals("7 key fix 7 M0 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 M0 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 M0 left", 3, params.mLeftKeys); + assertEquals("7 key fix 7 M0 right", 4, params.mRightKeys); + assertEquals("7 key fix 7 M0 [1]", -3, params.getColumnPos(0)); + assertEquals("7 key fix 7 M0 [2]", -2, params.getColumnPos(1)); + assertEquals("7 key fix 7 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key fix 7 M0 <4>", 0, params.getColumnPos(3)); + assertEquals("7 key fix 7 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key fix 7 M0 [6]", 2, params.getColumnPos(5)); + assertEquals("7 key fix 7 M0 [7]", 3, params.getColumnPos(6)); + assertEquals("7 key fix 7 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 M0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // |___ ___ [1] [2] [3] <4> [5] [6] [7] ___| + public void testLayout7KeyFix7M1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M1); + assertEquals("7 key fix 7 M1 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 M1 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 M1 left", 3, params.mLeftKeys); + assertEquals("7 key fix 7 M1 right", 4, params.mRightKeys); + assertEquals("7 key fix 7 M1 [1]", -3, params.getColumnPos(0)); + assertEquals("7 key fix 7 M1 [2]", -2, params.getColumnPos(1)); + assertEquals("7 key fix 7 M1 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key fix 7 M1 <4>", 0, params.getColumnPos(3)); + assertEquals("7 key fix 7 M1 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key fix 7 M1 [6]", 2, params.getColumnPos(5)); + assertEquals("7 key fix 7 M1 [7]", 3, params.getColumnPos(6)); + assertEquals("7 key fix 7 M1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 M1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] <5> [6] [7] ___| + public void testLayout7KeyFix7R3() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R3); + assertEquals("7 key fix 7 R3 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 R3 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 R3 left", 4, params.mLeftKeys); + assertEquals("7 key fix 7 R3 right", 3, params.mRightKeys); + assertEquals("7 key fix 7 R3 [1]", -4, params.getColumnPos(0)); + assertEquals("7 key fix 7 R3 [2]", -3, params.getColumnPos(1)); + assertEquals("7 key fix 7 R3 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key fix 7 R3 [4]", -1, params.getColumnPos(3)); + assertEquals("7 key fix 7 R3 <5>", 0, params.getColumnPos(4)); + assertEquals("7 key fix 7 R3 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key fix 7 R3 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key fix 7 R3 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 R3 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] [5] <6> [7] ___| + public void testLayout7KeyFix7R2() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R2); + assertEquals("7 key fix 7 R2 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 R2 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 R2 left", 5, params.mLeftKeys); + assertEquals("7 key fix 7 R2 right", 2, params.mRightKeys); + assertEquals("7 key fix 7 R2 [1]", -5, params.getColumnPos(0)); + assertEquals("7 key fix 7 R2 [2]", -4, params.getColumnPos(1)); + assertEquals("7 key fix 7 R2 [3]", -3, params.getColumnPos(2)); + assertEquals("7 key fix 7 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("7 key fix 7 R2 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key fix 7 R2 <6>", 0, params.getColumnPos(5)); + assertEquals("7 key fix 7 R2 [7]", 1, params.getColumnPos(6)); + assertEquals("7 key fix 7 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 R2 default", WIDTH * 5, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] [5] [6] <7> ___| + public void testLayout7KeyFix7R1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R1); + assertEquals("7 key fix 7 R1 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 R1 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 R1 left", 6, params.mLeftKeys); + assertEquals("7 key fix 7 R1 right", 1, params.mRightKeys); + assertEquals("7 key fix 7 R1 [1]", -6, params.getColumnPos(0)); + assertEquals("7 key fix 7 R1 [2]", -5, params.getColumnPos(1)); + assertEquals("7 key fix 7 R1 [3]", -4, params.getColumnPos(2)); + assertEquals("7 key fix 7 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key fix 7 R1 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key fix 7 R1 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 7 R1 <7>", 0, params.getColumnPos(6)); + assertEquals("7 key fix 7 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 R1 default", WIDTH * 6, params.getDefaultKeyCoordX()); + } + + // [1] [2] [3] [4] [5] [6] <7>| + public void testLayout7KeyFix7R0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R0); + assertEquals("7 key fix 7 R0 columns", 7, params.mNumColumns); + assertEquals("7 key fix 7 R0 rows", 1, params.mNumRows); + assertEquals("7 key fix 7 R0 left", 6, params.mLeftKeys); + assertEquals("7 key fix 7 R0 right", 1, params.mRightKeys); + assertEquals("7 key fix 7 R0 [1]", -6, params.getColumnPos(0)); + assertEquals("7 key fix 7 R0 [2]", -5, params.getColumnPos(1)); + assertEquals("7 key fix 7 R0 [3]", -4, params.getColumnPos(2)); + assertEquals("7 key fix 7 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key fix 7 R0 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key fix 7 R0 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key fix 7 R0 <7>", 0, params.getColumnPos(6)); + assertEquals("7 key fix 7 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key fix 7 R0 default", WIDTH * 6, params.getDefaultKeyCoordX()); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java new file mode 100644 index 000000000..31f0e0fef --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/MoreKeysKeyboardBuilderTests.java @@ -0,0 +1,2365 @@ +/* + * Copyright (C) 2011 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.keyboard; + +import android.test.AndroidTestCase; + +import com.android.inputmethod.keyboard.MoreKeysKeyboard.Builder.MoreKeysKeyboardParams; + +public class MoreKeysKeyboardBuilderTests extends AndroidTestCase { + private static final int WIDTH = 10; + private static final int HEIGHT = 10; + + private static final int KEYBOARD_WIDTH = WIDTH * 10; + private static final int XPOS_L0 = WIDTH * 0 + WIDTH / 2; + private static final int XPOS_L1 = WIDTH * 1 + WIDTH / 2; + private static final int XPOS_L2 = WIDTH * 2 + WIDTH / 2; + private static final int XPOS_L3 = WIDTH * 3 + WIDTH / 2; + private static final int XPOS_M0 = WIDTH * 4 + WIDTH / 2; + private static final int XPOS_M1 = WIDTH * 5 + WIDTH / 2; + private static final int XPOS_R3 = WIDTH * 6 + WIDTH / 2; + private static final int XPOS_R2 = WIDTH * 7 + WIDTH / 2; + private static final int XPOS_R1 = WIDTH * 8 + WIDTH / 2; + private static final int XPOS_R0 = WIDTH * 9 + WIDTH / 2; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + private static MoreKeysKeyboardParams createParams(int numKeys, int maxColumns, + int coordXInParnet) { + final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams(); + params.setParameters(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH, + /* isFixedOrderColumn */false, /* dividerWidth */0); + return params; + } + + public void testLayoutError() { + MoreKeysKeyboardParams params = null; + try { + final int maxColumns = KEYBOARD_WIDTH / WIDTH; + params = createParams(10, maxColumns + 1, HEIGHT); + fail("Should throw IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Too small keyboard to hold more keys keyboard. + } + assertNull("Too small keyboard to hold more keys keyboard", params); + } + + // More keys keyboard layout test. + // "[n]" represents n-th key position in more keys keyboard. + // "<1>" is the default key. + + // <1> + public void testLayout1KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_M0); + assertEquals("1 key max 5 M0 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 M0 rows", 1, params.mNumRows); + assertEquals("1 key max 5 M0 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 M0 right", 1, params.mRightKeys); + assertEquals("1 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |<1> + public void testLayout1KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L0); + assertEquals("1 key max 5 L0 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 L0 rows", 1, params.mNumRows); + assertEquals("1 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 L0 right", 1, params.mRightKeys); + assertEquals("1 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> + public void testLayout1KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L1); + assertEquals("1 key max 5 L1 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 L1 rows", 1, params.mNumRows); + assertEquals("1 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 L1 right", 1, params.mRightKeys); + assertEquals("1 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ <1> + public void testLayout1KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_L2); + assertEquals("1 key max 5 L2 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 L2 rows", 1, params.mNumRows); + assertEquals("1 key max 5 L2 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 L2 right", 1, params.mRightKeys); + assertEquals("1 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1>| + public void testLayout1KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R0); + assertEquals("1 key max 5 R0 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 R0 rows", 1, params.mNumRows); + assertEquals("1 key max 5 R0 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("1 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 R0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> ___| + public void testLayout1KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R1); + assertEquals("1 key max 5 R1 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 R1 rows", 1, params.mNumRows); + assertEquals("1 key max 5 R1 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("1 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 R1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> ___ ___| + public void testLayout1KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(1, 5, XPOS_R2); + assertEquals("1 key max 5 R2 columns", 1, params.mNumColumns); + assertEquals("1 key max 5 R2 rows", 1, params.mNumRows); + assertEquals("1 key max 5 R2 left", 0, params.mLeftKeys); + assertEquals("1 key max 5 R2 right", 1, params.mRightKeys); + assertEquals("1 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("1 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("1 key max 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // <1> [2] + public void testLayout2KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_M0); + assertEquals("2 key max 5 M0 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 M0 rows", 1, params.mNumRows); + assertEquals("2 key max 5 M0 left", 0, params.mLeftKeys); + assertEquals("2 key max 5 M0 right", 2, params.mRightKeys); + assertEquals("2 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |<1> [2] + public void testLayout2KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L0); + assertEquals("2 key max 5 L0 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 L0 rows", 1, params.mNumRows); + assertEquals("2 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("2 key max 5 L0 right", 2, params.mRightKeys); + assertEquals("2 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] + public void testLayout2KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L1); + assertEquals("2 key max 5 L1 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 L1 rows", 1, params.mNumRows); + assertEquals("2 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("2 key max 5 L1 right", 2, params.mRightKeys); + assertEquals("2 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ <1> [2] + public void testLayout2KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_L2); + assertEquals("2 key max 5 L2 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 L2 rows", 1, params.mNumRows); + assertEquals("2 key max 5 L2 left", 0, params.mLeftKeys); + assertEquals("2 key max 5 L2 right", 2, params.mRightKeys); + assertEquals("2 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [2] <1>| + public void testLayout2KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R0); + assertEquals("2 key max 5 R0 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 R0 rows", 1, params.mNumRows); + assertEquals("2 key max 5 R0 left", 1, params.mLeftKeys); + assertEquals("2 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("2 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("2 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [2] <1> ___| + public void testLayout2KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R1); + assertEquals("2 key max 5 R1 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 R1 rows", 1, params.mNumRows); + assertEquals("2 key max 5 R1 left", 1, params.mLeftKeys); + assertEquals("2 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("2 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("2 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // <1> [2] ___| + public void testLayout2KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(2, 5, XPOS_R2); + assertEquals("2 key max 5 R2 columns", 2, params.mNumColumns); + assertEquals("2 key max 5 R2 rows", 1, params.mNumRows); + assertEquals("2 key max 5 R2 left", 0, params.mLeftKeys); + assertEquals("2 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("2 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("2 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("2 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("2 key max 5 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] <1> [2] + public void testLayout3KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_M0); + assertEquals("3 key max 5 M0 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 M0 rows", 1, params.mNumRows); + assertEquals("3 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("3 key max 5 M0 right", 2, params.mRightKeys); + assertEquals("3 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("3 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] + public void testLayout3KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L0); + assertEquals("3 key max 5 L0 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 L0 rows", 1, params.mNumRows); + assertEquals("3 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("3 key max 5 L0 right", 3, params.mRightKeys); + assertEquals("3 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("3 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] + public void testLayout3KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L1); + assertEquals("3 key max 5 L1 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 L1 rows", 1, params.mNumRows); + assertEquals("3 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("3 key max 5 L1 right", 3, params.mRightKeys); + assertEquals("3 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("3 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] <1> [2] + public void testLayout3KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_L2); + assertEquals("3 key max 5 L2 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 L2 rows", 1, params.mNumRows); + assertEquals("3 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("3 key max 5 L2 right", 2, params.mRightKeys); + assertEquals("3 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("3 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] [2] <1>| + public void testLayout3KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R0); + assertEquals("3 key max 5 R0 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 R0 rows", 1, params.mNumRows); + assertEquals("3 key max 5 R0 left", 2, params.mLeftKeys); + assertEquals("3 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("3 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("3 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [3] [2] <1> ___| + public void testLayout3KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R1); + assertEquals("3 key max 5 R1 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 R1 rows", 1, params.mNumRows); + assertEquals("3 key max 5 R1 left", 2, params.mLeftKeys); + assertEquals("3 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("3 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("3 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [3] <1> [2] ___| + public void testLayout3KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(3, 5, XPOS_R2); + assertEquals("3 key max 5 R2 columns", 3, params.mNumColumns); + assertEquals("3 key max 5 R2 rows", 1, params.mNumRows); + assertEquals("3 key max 5 R2 left", 1, params.mLeftKeys); + assertEquals("3 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("3 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("3 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 5 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] + // <1> [2] + public void testLayout3KeyMax2M0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_M0); + assertEquals("3 key max 2 M0 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 M0 rows", 2, params.mNumRows); + assertEquals("3 key max 2 M0 left", 0, params.mLeftKeys); + assertEquals("3 key max 2 M0 right", 2, params.mRightKeys); + assertEquals("3 key max 2 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 2 M0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |[3] + // |<1> [2] + public void testLayout3KeyMax2L0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L0); + assertEquals("3 key max 2 L0 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 L0 rows", 2, params.mNumRows); + assertEquals("3 key max 2 L0 left", 0, params.mLeftKeys); + assertEquals("3 key max 2 L0 right", 2, params.mRightKeys); + assertEquals("3 key max 2 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 2 L0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] + // |___ <1> [2] + public void testLayout3KeyMax2L1() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L1); + assertEquals("3 key max 2 L1 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 L1 rows", 2, params.mNumRows); + assertEquals("3 key max 2 L1 left", 0, params.mLeftKeys); + assertEquals("3 key max 2 L1 right", 2, params.mRightKeys); + assertEquals("3 key max 2 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 2 L1 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // | [3] + // |___ ___ <1> [2] + public void testLayout3KeyMax2L2() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_L2); + assertEquals("3 key max 2 L2 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 L2 rows", 2, params.mNumRows); + assertEquals("3 key max 2 L2 left", 0, params.mLeftKeys); + assertEquals("3 key max 2 L2 right", 2, params.mRightKeys); + assertEquals("3 key max 2 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 2 L2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3]| + // [2] <1>| + public void testLayout3KeyMax2R0() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R0); + assertEquals("3 key max 2 R0 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 R0 rows", 2, params.mNumRows); + assertEquals("3 key max 2 R0 left", 1, params.mLeftKeys); + assertEquals("3 key max 2 R0 right", 1, params.mRightKeys); + assertEquals("3 key max 2 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key max 2 R0 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] | + // [2] <1> ___| + public void testLayout3KeyMax2R1() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R1); + assertEquals("3 key max 2 R1 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 R1 rows", 2, params.mNumRows); + assertEquals("3 key max 2 R1 left", 1, params.mLeftKeys); + assertEquals("3 key max 2 R1 right", 1, params.mRightKeys); + assertEquals("3 key max 2 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("3 key max 2 R1 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] | + // <1> [2] ___| + public void testLayout3KeyMax2R2() { + MoreKeysKeyboardParams params = createParams(3, 2, XPOS_R2); + assertEquals("3 key max 2 R2 columns", 2, params.mNumColumns); + assertEquals("3 key max 2 R2 rows", 2, params.mNumRows); + assertEquals("3 key max 2 R2 left", 0, params.mLeftKeys); + assertEquals("3 key max 2 R2 right", 2, params.mRightKeys); + assertEquals("3 key max 2 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("3 key max 2 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("3 key max 2 R2 [3]", 0, params.getColumnPos(2)); + assertEquals("3 key max 2 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("3 key max 2 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] [4] + // <1> [2] + public void testLayout4KeyMax3M0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_M0); + assertEquals("4 key max 3 M0 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 M0 rows", 2, params.mNumRows); + assertEquals("4 key max 3 M0 left", 0, params.mLeftKeys); + assertEquals("4 key max 3 M0 right", 2, params.mRightKeys); + assertEquals("4 key max 3 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 3 M0 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 M0 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key max 3 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 M0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |[3] [4] + // |<1> [2] + public void testLayout4KeyMax3L0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L0); + assertEquals("4 key max 3 L0 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 L0 rows", 2, params.mNumRows); + assertEquals("4 key max 3 L0 left", 0, params.mLeftKeys); + assertEquals("4 key max 3 L0 right", 2, params.mRightKeys); + assertEquals("4 key max 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 3 L0 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 L0 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key max 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] [4] + // |___ <1> [2] + public void testLayout4KeyMax3L1() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L1); + assertEquals("4 key max 3 L1 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 L1 rows", 2, params.mNumRows); + assertEquals("4 key max 3 L1 left", 0, params.mLeftKeys); + assertEquals("4 key max 3 L1 right", 2, params.mRightKeys); + assertEquals("4 key max 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 3 L1 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 L1 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key max 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ ___ [3] [4] + // |___ ___ <1> [2] + public void testLayout4KeyMax3L2() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_L2); + assertEquals("4 key max 3 L2 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 L2 rows", 2, params.mNumRows); + assertEquals("4 key max 3 L2 left", 0, params.mLeftKeys); + assertEquals("4 key max 3 L2 right", 2, params.mRightKeys); + assertEquals("4 key max 3 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 3 L2 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 L2 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key max 3 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 L2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [4] [3]| + // [2] <1>| + public void testLayout4KeyMax3R0() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R0); + assertEquals("4 key max 3 R0 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 R0 rows", 2, params.mNumRows); + assertEquals("4 key max 3 R0 left", 1, params.mLeftKeys); + assertEquals("4 key max 3 R0 right", 1, params.mRightKeys); + assertEquals("4 key max 3 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 3 R0 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 R0 [4]", -1, params.getColumnPos(3)); + assertEquals("4 key max 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 R0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [3] ___| + // [2] <1> ___| + public void testLayout4KeyMax3R1() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R1); + assertEquals("4 key max 3 R1 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 R1 rows", 2, params.mNumRows); + assertEquals("4 key max 3 R1 left", 1, params.mLeftKeys); + assertEquals("4 key max 3 R1 right", 1, params.mRightKeys); + assertEquals("4 key max 3 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 3 R1 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 R1 [4]", -1, params.getColumnPos(3)); + assertEquals("4 key max 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 R1 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [3] [4] ___| + // <1> [2] ___| + public void testLayout4KeyMax3R2() { + MoreKeysKeyboardParams params = createParams(4, 3, XPOS_R2); + assertEquals("4 key max 3 R2 columns", 2, params.mNumColumns); + assertEquals("4 key max 3 R2 rows", 2, params.mNumRows); + assertEquals("4 key max 3 R2 left", 0, params.mLeftKeys); + assertEquals("4 key max 3 R2 right", 2, params.mRightKeys); + assertEquals("4 key max 3 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 3 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 3 R2 [3]", 0, params.getColumnPos(2)); + assertEquals("4 key max 3 R2 [4]", 1, params.getColumnPos(3)); + assertEquals("4 key max 3 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 3 R2 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // [3] <1> [2] [4] + public void testLayout4KeyMax4M0() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_M0); + assertEquals("4 key max 4 M0 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 M0 rows", 1, params.mNumRows); + assertEquals("4 key max 4 M0 left", 1, params.mLeftKeys); + assertEquals("4 key max 4 M0 right", 3, params.mRightKeys); + assertEquals("4 key max 4 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 4 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 4 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key max 4 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] + public void testLayout4KeyMax4L0() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L0); + assertEquals("4 key max 4 L0 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 L0 rows", 1, params.mNumRows); + assertEquals("4 key max 4 L0 left", 0, params.mLeftKeys); + assertEquals("4 key max 4 L0 right", 4, params.mRightKeys); + assertEquals("4 key max 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key max 4 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key max 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] + public void testLayout4KeyMax4L1() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L1); + assertEquals("4 key max 4 L1 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 L1 rows", 1, params.mNumRows); + assertEquals("4 key max 4 L1 left", 0, params.mLeftKeys); + assertEquals("4 key max 4 L1 right", 4, params.mRightKeys); + assertEquals("4 key max 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key max 4 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key max 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] <1> [2] [4] + public void testLayout4KeyMax4L2() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_L2); + assertEquals("4 key max 4 L2 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 L2 rows", 1, params.mNumRows); + assertEquals("4 key max 4 L2 left", 1, params.mLeftKeys); + assertEquals("4 key max 4 L2 right", 3, params.mRightKeys); + assertEquals("4 key max 4 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 4 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 4 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key max 4 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [3] [2] <1>| + public void testLayout4KeyMax4R0() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R0); + assertEquals("4 key max 4 R0 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 R0 rows", 1, params.mNumRows); + assertEquals("4 key max 4 R0 left", 3, params.mLeftKeys); + assertEquals("4 key max 4 R0 right", 1, params.mRightKeys); + assertEquals("4 key max 4 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 4 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("4 key max 4 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("4 key max 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [4] [3] [2] <1> ___| + public void testLayout4KeyMax4R1() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R1); + assertEquals("4 key max 4 R1 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 R1 rows", 1, params.mNumRows); + assertEquals("4 key max 4 R1 left", 3, params.mLeftKeys); + assertEquals("4 key max 4 R1 right", 1, params.mRightKeys); + assertEquals("4 key max 4 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 4 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("4 key max 4 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("4 key max 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [4] [3] <1> [2] ___| + public void testLayout4KeyMax4R2() { + MoreKeysKeyboardParams params = createParams(4, 4, XPOS_R2); + assertEquals("4 key max 4 R2 columns", 4, params.mNumColumns); + assertEquals("4 key max 4 R2 rows", 1, params.mNumRows); + assertEquals("4 key max 4 R2 left", 2, params.mLeftKeys); + assertEquals("4 key max 4 R2 right", 2, params.mRightKeys); + assertEquals("4 key max 4 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 4 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 4 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 4 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("4 key max 4 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 4 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [3] <1> [2] [4] + public void testLayout4KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_M0); + assertEquals("4 key max 5 M0 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 M0 rows", 1, params.mNumRows); + assertEquals("4 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("4 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("4 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] + public void testLayout4KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L0); + assertEquals("4 key max 5 L0 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 L0 rows", 1, params.mNumRows); + assertEquals("4 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("4 key max 5 L0 right", 4, params.mRightKeys); + assertEquals("4 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] + public void testLayout4KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L1); + assertEquals("4 key max 5 L1 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 L1 rows", 1, params.mNumRows); + assertEquals("4 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("4 key max 5 L1 right", 4, params.mRightKeys); + assertEquals("4 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("4 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("4 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] <1> [2] [4] + public void testLayout4KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_L2); + assertEquals("4 key max 5 L2 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 L2 rows", 1, params.mNumRows); + assertEquals("4 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("4 key max 5 L2 right", 3, params.mRightKeys); + assertEquals("4 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("4 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [3] [2] <1>| + public void testLayout4KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R0); + assertEquals("4 key max 5 R0 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 R0 rows", 1, params.mNumRows); + assertEquals("4 key max 5 R0 left", 3, params.mLeftKeys); + assertEquals("4 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("4 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("4 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("4 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [4] [3] [2] <1> ___| + public void testLayout4KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R1); + assertEquals("4 key max 5 R1 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 R1 rows", 1, params.mNumRows); + assertEquals("4 key max 5 R1 left", 3, params.mLeftKeys); + assertEquals("4 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("4 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("4 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("4 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("4 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [4] [3] <1> [2] ___| + public void testLayout4KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(4, 5, XPOS_R2); + assertEquals("4 key max 5 R2 columns", 4, params.mNumColumns); + assertEquals("4 key max 5 R2 rows", 1, params.mNumRows); + assertEquals("4 key max 5 R2 left", 2, params.mLeftKeys); + assertEquals("4 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("4 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("4 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("4 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("4 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("4 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("4 key max 5 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] + // [3] <1> [2] + public void testLayout5KeyMax3M0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_M0); + assertEquals("5 key max 3 M0 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 M0 rows", 2, params.mNumRows); + assertEquals("5 key max 3 M0 left", 1, params.mLeftKeys); + assertEquals("5 key max 3 M0 right", 2, params.mRightKeys); + assertEquals("5 key max 3 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 3 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 3 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 3 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] + // |<1> [2] [3] + public void testLayout5KeyMax3L0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L0); + assertEquals("5 key max 3 L0 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 L0 rows", 2, params.mNumRows); + assertEquals("5 key max 3 L0 left", 0, params.mLeftKeys); + assertEquals("5 key max 3 L0 right", 3, params.mRightKeys); + assertEquals("5 key max 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 3 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 3 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ <1> [2] [3] + public void testLayout5KeyMax3L1() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L1); + assertEquals("5 key max 3 L1 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 L1 rows", 2, params.mNumRows); + assertEquals("5 key max 3 L1 left", 0, params.mLeftKeys); + assertEquals("5 key max 3 L1 right", 3, params.mRightKeys); + assertEquals("5 key max 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 3 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 3 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ [3] <1> [2] + public void testLayout5KeyMax3L2() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_L2); + assertEquals("5 key max 3 L2 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 L2 rows", 2, params.mNumRows); + assertEquals("5 key max 3 L2 left", 1, params.mLeftKeys); + assertEquals("5 key max 3 L2 right", 2, params.mRightKeys); + assertEquals("5 key max 3 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 3 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 3 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 3 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [4]| + // [3] [2] <1>| + public void testLayout5KeyMax3R0() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R0); + assertEquals("5 key max 3 R0 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 R0 rows", 2, params.mNumRows); + assertEquals("5 key max 3 R0 left", 2, params.mLeftKeys); + assertEquals("5 key max 3 R0 right", 1, params.mRightKeys); + assertEquals("5 key max 3 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 3 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 3 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("5 key max 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] [4] ___| + // [3] [2] <1> ___| + public void testLayout5KeyMax3R1() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R1); + assertEquals("5 key max 3 R1 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 R1 rows", 2, params.mNumRows); + assertEquals("5 key max 3 R1 left", 2, params.mLeftKeys); + assertEquals("5 key max 3 R1 right", 1, params.mRightKeys); + assertEquals("5 key max 3 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 3 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 3 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("5 key max 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] ___| + // [3] <1> [2] ___| + public void testLayout5KeyMax3R2() { + MoreKeysKeyboardParams params = createParams(5, 3, XPOS_R2); + assertEquals("5 key max 3 R2 columns", 3, params.mNumColumns); + assertEquals("5 key max 3 R2 rows", 2, params.mNumRows); + assertEquals("5 key max 3 R2 left", 1, params.mLeftKeys); + assertEquals("5 key max 3 R2 right", 2, params.mRightKeys); + assertEquals("5 key max 3 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 3 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 3 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 3 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 3 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 3 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [4] [5] + // [3] <1> [2] + public void testLayout5KeyMax4M0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_M0); + assertEquals("5 key max 4 M0 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 M0 rows", 2, params.mNumRows); + assertEquals("5 key max 4 M0 left", 1, params.mLeftKeys); + assertEquals("5 key max 4 M0 right", 2, params.mRightKeys); + assertEquals("5 key max 4 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 4 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 4 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 4 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] + // |<1> [2] [3] + public void testLayout5KeyMax4L0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L0); + assertEquals("5 key max 4 L0 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 L0 rows", 2, params.mNumRows); + assertEquals("5 key max 4 L0 left", 0, params.mLeftKeys); + assertEquals("5 key max 4 L0 right", 3, params.mRightKeys); + assertEquals("5 key max 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 4 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ <1> [2] [3] + public void testLayout5KeyMax4L1() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L1); + assertEquals("5 key max 4 L1 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 L1 rows", 2, params.mNumRows); + assertEquals("5 key max 4 L1 left", 0, params.mLeftKeys); + assertEquals("5 key max 4 L1 right", 3, params.mRightKeys); + assertEquals("5 key max 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 4 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] + // |___ [3] <1> [2] + public void testLayout5KeyMax4L2() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_L2); + assertEquals("5 key max 4 L2 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 L2 rows", 2, params.mNumRows); + assertEquals("5 key max 4 L2 left", 1, params.mLeftKeys); + assertEquals("5 key max 4 L2 right", 2, params.mRightKeys); + assertEquals("5 key max 4 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 4 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 4 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 4 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [4]| + // [3] [2] <1>| + public void testLayout5KeyMax4R0() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R0); + assertEquals("5 key max 4 R0 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 R0 rows", 2, params.mNumRows); + assertEquals("5 key max 4 R0 left", 2, params.mLeftKeys); + assertEquals("5 key max 4 R0 right", 1, params.mRightKeys); + assertEquals("5 key max 4 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 4 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 4 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("5 key max 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 4 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [5] [4] ___| + // [3] [2] <1> ___| + public void testLayout5KeyMax4R1() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R1); + assertEquals("5 key max 4 R1 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 R1 rows", 2, params.mNumRows); + assertEquals("5 key max 4 R1 left", 2, params.mLeftKeys); + assertEquals("5 key max 4 R1 right", 1, params.mRightKeys); + assertEquals("5 key max 4 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 4 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 4 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("5 key max 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 4 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [4] [5] ___| + // [3] <1> [2] ___| + public void testLayout5KeyMax4R2() { + MoreKeysKeyboardParams params = createParams(5, 4, XPOS_R2); + assertEquals("5 key max 4 R2 columns", 3, params.mNumColumns); + assertEquals("5 key max 4 R2 rows", 2, params.mNumRows); + assertEquals("5 key max 4 R2 left", 1, params.mLeftKeys); + assertEquals("5 key max 4 R2 right", 2, params.mRightKeys); + assertEquals("5 key max 4 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 4 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 4 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 4 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("5 key max 4 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("5 key max 4 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("5 key max 4 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [3] <1> [2] [4] + public void testLayout5KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_M0); + assertEquals("5 key max 5 M0 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 M0 rows", 1, params.mNumRows); + assertEquals("5 key max 5 M0 left", 2, params.mLeftKeys); + assertEquals("5 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("5 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("5 key max 5 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("5 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] [5] + public void testLayout5KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L0); + assertEquals("5 key max 5 L0 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 L0 rows", 1, params.mNumRows); + assertEquals("5 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("5 key max 5 L0 right", 5, params.mRightKeys); + assertEquals("5 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key max 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("5 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] [5] + public void testLayout5KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L1); + assertEquals("5 key max 5 L1 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 L1 rows", 1, params.mNumRows); + assertEquals("5 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("5 key max 5 L1 right", 5, params.mRightKeys); + assertEquals("5 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("5 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("5 key max 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("5 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] <1> [2] [4] [5] + public void testLayout5KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_L2); + assertEquals("5 key max 5 L2 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 L2 rows", 1, params.mNumRows); + assertEquals("5 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("5 key max 5 L2 right", 4, params.mRightKeys); + assertEquals("5 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("5 key max 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("5 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [5] [4] [3] [2] <1>| + public void testLayout5KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R0); + assertEquals("5 key max 5 R0 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 R0 rows", 1, params.mNumRows); + assertEquals("5 key max 5 R0 left", 4, params.mLeftKeys); + assertEquals("5 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("5 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("5 key max 5 R0 [5]", -4, params.getColumnPos(4)); + assertEquals("5 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [5] [4] [3] [2] <1> ___| + public void testLayout5KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R1); + assertEquals("5 key max 5 R1 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 R1 rows", 1, params.mNumRows); + assertEquals("5 key max 5 R1 left", 4, params.mLeftKeys); + assertEquals("5 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("5 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("5 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("5 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("5 key max 5 R1 [5]", -4, params.getColumnPos(4)); + assertEquals("5 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [5] [4] [3] <1> [2] ___| + public void testLayout5KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(5, 5, XPOS_R2); + assertEquals("5 key max 5 R2 columns", 5, params.mNumColumns); + assertEquals("5 key max 5 R2 rows", 1, params.mNumRows); + assertEquals("5 key max 5 R2 left", 3, params.mLeftKeys); + assertEquals("5 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("5 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("5 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("5 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("5 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("5 key max 5 R2 [5]", -3, params.getColumnPos(4)); + assertEquals("5 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("5 key max 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [6] [4] [5] + // [3] <1> [2] + public void testLayout6KeyMax4M0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_M0); + assertEquals("6 key max 4 M0 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 M0 rows", 2, params.mNumRows); + assertEquals("6 key max 4 M0 left", 1, params.mLeftKeys); + assertEquals("6 key max 4 M0 right", 2, params.mRightKeys); + assertEquals("6 key max 4 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 4 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 4 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 4 M0 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 4 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] [6] + // |<1> [2] [3] + public void testLayout6KeyMax4L0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L0); + assertEquals("6 key max 4 L0 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 L0 rows", 2, params.mNumRows); + assertEquals("6 key max 4 L0 left", 0, params.mLeftKeys); + assertEquals("6 key max 4 L0 right", 3, params.mRightKeys); + assertEquals("6 key max 4 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 4 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key max 4 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 4 L0 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key max 4 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] [6] + // |___ <1> [2] [3] + public void testLayout6KeyMax4L1() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L1); + assertEquals("6 key max 4 L1 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 L1 rows", 2, params.mNumRows); + assertEquals("6 key max 4 L1 left", 0, params.mLeftKeys); + assertEquals("6 key max 4 L1 right", 3, params.mRightKeys); + assertEquals("6 key max 4 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 4 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key max 4 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 4 L1 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key max 4 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [4] [5] + // |___ [3] <1> [2] + public void testLayout6KeyMax4L2() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_L2); + assertEquals("6 key max 4 L2 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 L2 rows", 2, params.mNumRows); + assertEquals("6 key max 4 L2 left", 1, params.mLeftKeys); + assertEquals("6 key max 4 L2 right", 2, params.mRightKeys); + assertEquals("6 key max 4 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 4 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 4 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 4 L2 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 4 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [5] [4]| + // [3] [2] <1>| + public void testLayout6KeyMax4R0() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R0); + assertEquals("6 key max 4 R0 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 R0 rows", 2, params.mNumRows); + assertEquals("6 key max 4 R0 left", 2, params.mLeftKeys); + assertEquals("6 key max 4 R0 right", 1, params.mRightKeys); + assertEquals("6 key max 4 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key max 4 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key max 4 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key max 4 R0 [6]", -2, params.getColumnPos(5)); + assertEquals("6 key max 4 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [6] [5] [4] ___| + // [3] [2] <1> ___| + public void testLayout6KeyMax4R1() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R1); + assertEquals("6 key max 4 R1 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 R1 rows", 2, params.mNumRows); + assertEquals("6 key max 4 R1 left", 2, params.mLeftKeys); + assertEquals("6 key max 4 R1 right", 1, params.mRightKeys); + assertEquals("6 key max 4 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key max 4 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key max 4 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key max 4 R1 [6]", -2, params.getColumnPos(5)); + assertEquals("6 key max 4 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [6] [4] [5] ___| + // [3] <1> [2] ___| + public void testLayout6KeyMax4R2() { + MoreKeysKeyboardParams params = createParams(6, 4, XPOS_R2); + assertEquals("6 key max 4 R2 columns", 3, params.mNumColumns); + assertEquals("6 key max 4 R2 rows", 2, params.mNumRows); + assertEquals("6 key max 4 R2 left", 1, params.mLeftKeys); + assertEquals("6 key max 4 R2 right", 2, params.mRightKeys); + assertEquals("6 key max 4 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 4 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 4 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 4 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 4 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 4 R2 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 4 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 4 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [4] [5] + // [3] <1> [2] + public void testLayout6KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_M0); + assertEquals("6 key max 5 M0 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 M0 rows", 2, params.mNumRows); + assertEquals("6 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("6 key max 5 M0 right", 2, params.mRightKeys); + assertEquals("6 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 5 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 5 M0 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[4] [5] [6] + // |<1> [2] [3] + public void testLayout6KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L0); + assertEquals("6 key max 5 L0 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 L0 rows", 2, params.mNumRows); + assertEquals("6 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("6 key max 5 L0 right", 3, params.mRightKeys); + assertEquals("6 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key max 5 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 5 L0 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [4] [5] [6] + // |___ <1> [2] [3] + public void testLayout6KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L1); + assertEquals("6 key max 5 L1 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 L1 rows", 2, params.mNumRows); + assertEquals("6 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("6 key max 5 L1 right", 3, params.mRightKeys); + assertEquals("6 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("6 key max 5 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 5 L1 [6]", 2, params.getColumnPos(5)); + assertEquals("6 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [4] [5] + // |___ [3] <1> [2] + public void testLayout6KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_L2); + assertEquals("6 key max 5 L2 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 L2 rows", 2, params.mNumRows); + assertEquals("6 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("6 key max 5 L2 right", 2, params.mRightKeys); + assertEquals("6 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 5 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 5 L2 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [6] [5] [4]| + // [3] [2] <1>| + public void testLayout6KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R0); + assertEquals("6 key max 5 R0 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 R0 rows", 2, params.mNumRows); + assertEquals("6 key max 5 R0 left", 2, params.mLeftKeys); + assertEquals("6 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("6 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key max 5 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key max 5 R0 [6]", -2, params.getColumnPos(5)); + assertEquals("6 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [6] [5] [4] ___| + // [3] [2] <1> ___| + public void testLayout6KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R1); + assertEquals("6 key max 5 R1 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 R1 rows", 2, params.mNumRows); + assertEquals("6 key max 5 R1 left", 2, params.mLeftKeys); + assertEquals("6 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("6 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("6 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("6 key max 5 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("6 key max 5 R1 [6]", -2, params.getColumnPos(5)); + assertEquals("6 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [6] [4] [5] ___| + // [3] <1> [2] ___| + public void testLayout6KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(6, 5, XPOS_R2); + assertEquals("6 key max 5 R2 columns", 3, params.mNumColumns); + assertEquals("6 key max 5 R2 rows", 2, params.mNumRows); + assertEquals("6 key max 5 R2 left", 1, params.mLeftKeys); + assertEquals("6 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("6 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("6 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("6 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("6 key max 5 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("6 key max 5 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("6 key max 5 R2 [6]", -1, params.getColumnPos(5)); + assertEquals("6 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("6 key max 5 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |<1> [2] [3] [4] [5] [6] [7] ___ ___ ___| + public void testLayout7KeyMax7L0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L0); + assertEquals("7 key max 7 L0 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 L0 rows", 1, params.mNumRows); + assertEquals("7 key max 7 L0 left", 0, params.mLeftKeys); + assertEquals("7 key max 7 L0 right", 7, params.mRightKeys); + assertEquals("7 key max 7 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 7 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key max 7 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key max 7 L0 [6]", 5, params.getColumnPos(5)); + assertEquals("7 key max 7 L0 [7]", 6, params.getColumnPos(6)); + assertEquals("7 key max 7 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ <1> [2] [3] [4] [5] [6] [7] ___ ___| + public void testLayout7KeyMax7L1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L1); + assertEquals("7 key max 7 L1 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 L1 rows", 1, params.mNumRows); + assertEquals("7 key max 7 L1 left", 0, params.mLeftKeys); + assertEquals("7 key max 7 L1 right", 7, params.mRightKeys); + assertEquals("7 key max 7 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 7 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key max 7 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("7 key max 7 L1 [6]", 5, params.getColumnPos(5)); + assertEquals("7 key max 7 L1 [7]", 6, params.getColumnPos(6)); + assertEquals("7 key max 7 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [3] <1> [2] [4] [5] [6] [7] ___ ___| + public void testLayout7KeyMax7L2() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L2); + assertEquals("7 key max 7 L2 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 L2 rows", 1, params.mNumRows); + assertEquals("7 key max 7 L2 left", 1, params.mLeftKeys); + assertEquals("7 key max 7 L2 right", 6, params.mRightKeys); + assertEquals("7 key max 7 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 7 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("7 key max 7 L2 [6]", 4, params.getColumnPos(5)); + assertEquals("7 key max 7 L2 [7]", 5, params.getColumnPos(6)); + assertEquals("7 key max 7 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |___ [5] [3] <1> [2] [4] [6] [7] ___ ___| + public void testLayout7KeyMax7L3() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_L3); + assertEquals("7 key max 7 L3 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 L3 rows", 1, params.mNumRows); + assertEquals("7 key max 7 L3 left", 2, params.mLeftKeys); + assertEquals("7 key max 7 L3 right", 5, params.mRightKeys); + assertEquals("7 key max 7 L3 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 L3 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 L3 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 L3 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 7 L3 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key max 7 L3 [6]", 3, params.getColumnPos(5)); + assertEquals("7 key max 7 L3 [7]", 4, params.getColumnPos(6)); + assertEquals("7 key max 7 L3 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 L3 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |___ [7] [5] [3] <1> [2] [4] [6] ___ ___| + public void testLayout7KeyMax7M0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M0); + assertEquals("7 key max 7 M0 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 M0 rows", 1, params.mNumRows); + assertEquals("7 key max 7 M0 left", 3, params.mLeftKeys); + assertEquals("7 key max 7 M0 right", 4, params.mRightKeys); + assertEquals("7 key max 7 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 7 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key max 7 M0 [6]", 3, params.getColumnPos(5)); + assertEquals("7 key max 7 M0 [7]", -3, params.getColumnPos(6)); + assertEquals("7 key max 7 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 M0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // |___ ___ [7] [5] [3] <1> [2] [4] [6] ___| + public void testLayout7KeyMax7M1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_M1); + assertEquals("7 key max 7 M1 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 M1 rows", 1, params.mNumRows); + assertEquals("7 key max 7 M1 left", 3, params.mLeftKeys); + assertEquals("7 key max 7 M1 right", 4, params.mRightKeys); + assertEquals("7 key max 7 M1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 M1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 M1 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 M1 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 7 M1 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key max 7 M1 [6]", 3, params.getColumnPos(5)); + assertEquals("7 key max 7 M1 [7]", -3, params.getColumnPos(6)); + assertEquals("7 key max 7 M1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 M1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // |___ ___ [7] [6] [5] [3] <1> [2] [4] ___| + public void testLayout7KeyMax7R3() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R3); + assertEquals("7 key max 7 R3 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 R3 rows", 1, params.mNumRows); + assertEquals("7 key max 7 R3 left", 4, params.mLeftKeys); + assertEquals("7 key max 7 R3 right", 3, params.mRightKeys); + assertEquals("7 key max 7 R3 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 R3 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 R3 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 R3 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 7 R3 [5]", -2, params.getColumnPos(4)); + assertEquals("7 key max 7 R3 [6]", -3, params.getColumnPos(5)); + assertEquals("7 key max 7 R3 [7]", -4, params.getColumnPos(6)); + assertEquals("7 key max 7 R3 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 R3 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // |___ ___ [7] [6] [5] [4] [3] <1> [2] ___| + public void testLayout7KeyMax7R2() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R2); + assertEquals("7 key max 7 R2 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 R2 rows", 1, params.mNumRows); + assertEquals("7 key max 7 R2 left", 5, params.mLeftKeys); + assertEquals("7 key max 7 R2 right", 2, params.mRightKeys); + assertEquals("7 key max 7 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 7 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 7 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("7 key max 7 R2 [5]", -3, params.getColumnPos(4)); + assertEquals("7 key max 7 R2 [6]", -4, params.getColumnPos(5)); + assertEquals("7 key max 7 R2 [7]", -5, params.getColumnPos(6)); + assertEquals("7 key max 7 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 R2 default", WIDTH * 5, params.getDefaultKeyCoordX()); + } + + // |___ ___ [7] [6] [5] [4] [3] [2] <1> ___| + public void testLayout7KeyMax7R1() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R1); + assertEquals("7 key max 7 R1 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 R1 rows", 1, params.mNumRows); + assertEquals("7 key max 7 R1 left", 6, params.mLeftKeys); + assertEquals("7 key max 7 R1 right", 1, params.mRightKeys); + assertEquals("7 key max 7 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 7 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 7 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key max 7 R1 [5]", -4, params.getColumnPos(4)); + assertEquals("7 key max 7 R1 [6]", -5, params.getColumnPos(5)); + assertEquals("7 key max 7 R1 [7]", -6, params.getColumnPos(6)); + assertEquals("7 key max 7 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 R1 default", WIDTH * 6, params.getDefaultKeyCoordX()); + } + + // |___ ___ [7] [6] [5] [4] [3] [2] <1>| + public void testLayout7KeyMax7R0() { + MoreKeysKeyboardParams params = createParams(7, 7, XPOS_R0); + assertEquals("7 key max 7 R0 columns", 7, params.mNumColumns); + assertEquals("7 key max 7 R0 rows", 1, params.mNumRows); + assertEquals("7 key max 7 R0 left", 6, params.mLeftKeys); + assertEquals("7 key max 7 R0 right", 1, params.mRightKeys); + assertEquals("7 key max 7 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 7 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 7 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 7 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key max 7 R0 [5]", -4, params.getColumnPos(4)); + assertEquals("7 key max 7 R0 [6]", -5, params.getColumnPos(5)); + assertEquals("7 key max 7 R0 [7]", -6, params.getColumnPos(6)); + assertEquals("7 key max 7 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 7 R0 default", WIDTH * 6, params.getDefaultKeyCoordX()); + } + + // [5] [6] [7] + // [3] <1> [2] [4] + public void testLayout7KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_M0); + assertEquals("7 key max 5 M0 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 M0 rows", 2, params.mNumRows); + assertEquals("7 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("7 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("7 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 5 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key max 5 M0 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key max 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] [6] [7] + // |<1> [2] [3] [4] + public void testLayout7KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L0); + assertEquals("7 key max 5 L0 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 L0 rows", 2, params.mNumRows); + assertEquals("7 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("7 key max 5 L0 right", 4, params.mRightKeys); + assertEquals("7 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key max 5 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 L0 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key max 5 L0 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] + // |___ <1> [2] [3] [4] + public void testLayout7KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L1); + assertEquals("7 key max 5 L1 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 L1 rows", 2, params.mNumRows); + assertEquals("7 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("7 key max 5 L1 right", 4, params.mRightKeys); + assertEquals("7 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("7 key max 5 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 L1 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key max 5 L1 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] + // |___ [3] <1> [2] [4] + public void testLayout7KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_L2); + assertEquals("7 key max 5 L2 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 L2 rows", 2, params.mNumRows); + assertEquals("7 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("7 key max 5 L2 right", 3, params.mRightKeys); + assertEquals("7 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("7 key max 5 L2 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 L2 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key max 5 L2 [7]", 2, params.getColumnPos(6)); + assertEquals("7 key max 5 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [7] [6] [5]| + // [4] [3] [2] <1>| + public void testLayout7KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R0); + assertEquals("7 key max 5 R0 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 R0 rows", 2, params.mNumRows); + assertEquals("7 key max 5 R0 left", 3, params.mLeftKeys); + assertEquals("7 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("7 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key max 5 R0 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 R0 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key max 5 R0 [7]", -2, params.getColumnPos(6)); + assertEquals("7 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 5 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [7] [6] [5] ___| + // [4] [3] [2] <1> ___| + public void testLayout7KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R1); + assertEquals("7 key max 5 R1 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 R1 rows", 2, params.mNumRows); + assertEquals("7 key max 5 R1 left", 3, params.mLeftKeys); + assertEquals("7 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("7 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("7 key max 5 R1 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 R1 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key max 5 R1 [7]", -2, params.getColumnPos(6)); + assertEquals("7 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 5 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [7] [5] [6] ___| + // [4] [3] <1> [2] ___| + public void testLayout7KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(7, 5, XPOS_R2); + assertEquals("7 key max 5 R2 columns", 4, params.mNumColumns); + assertEquals("7 key max 5 R2 rows", 2, params.mNumRows); + assertEquals("7 key max 5 R2 left", 2, params.mLeftKeys); + assertEquals("7 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("7 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("7 key max 5 R2 [5]", 0, params.getColumnPos(4)); + assertEquals("7 key max 5 R2 [6]", 1, params.getColumnPos(5)); + assertEquals("7 key max 5 R2 [7]", -1, params.getColumnPos(6)); + assertEquals("7 key max 5 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("7 key max 5 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [7] + // [6] [4] [5] + // [3] <1> [2] + public void testLayout7KeyMax3M0() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_M0); + assertEquals("7 key max 3 M0 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 M0 rows", 3, params.mNumRows); + assertEquals("7 key max 3 M0 left", 1, params.mLeftKeys); + assertEquals("7 key max 3 M0 right", 2, params.mRightKeys); + assertEquals("7 key max 3 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 3 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 3 M0 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 M0 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key max 3 M0 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key max 3 M0 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[7] + // |[4] [5] [6] + // |<1> [2] [3] + public void testLayout7KeyMax3L0() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L0); + assertEquals("7 key max 3 L0 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 L0 rows", 3, params.mNumRows); + assertEquals("7 key max 3 L0 left", 0, params.mLeftKeys); + assertEquals("7 key max 3 L0 right", 3, params.mRightKeys); + assertEquals("7 key max 3 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 3 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 3 L0 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 L0 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key max 3 L0 [6]", 2, params.getColumnPos(5)); + assertEquals("7 key max 3 L0 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [7] + // |___ [4] [5] [6] + // |___ <1> [2] [3] + public void testLayout7KeyMax3L1() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L1); + assertEquals("7 key max 3 L1 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 L1 rows", 3, params.mNumRows); + assertEquals("7 key max 3 L1 left", 0, params.mLeftKeys); + assertEquals("7 key max 3 L1 right", 3, params.mRightKeys); + assertEquals("7 key max 3 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 3 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("7 key max 3 L1 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 L1 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key max 3 L1 [6]", 2, params.getColumnPos(5)); + assertEquals("7 key max 3 L1 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [7] + // |___ [6] [4] [5] + // |___ [3] <1> [2] + public void testLayout7KeyMax3L2() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_L2); + assertEquals("7 key max 3 L2 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 L2 rows", 3, params.mNumRows); + assertEquals("7 key max 3 L2 left", 1, params.mLeftKeys); + assertEquals("7 key max 3 L2 right", 2, params.mRightKeys); + assertEquals("7 key max 3 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 3 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 3 L2 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 L2 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key max 3 L2 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key max 3 L2 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [7]| + // [6] [5] [4]| + // [3] [2] <1>| + public void testLayout7KeyMax3R0() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R0); + assertEquals("7 key max 3 R0 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 R0 rows", 3, params.mNumRows); + assertEquals("7 key max 3 R0 left", 2, params.mLeftKeys); + assertEquals("7 key max 3 R0 right", 1, params.mRightKeys); + assertEquals("7 key max 3 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 3 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 3 R0 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 R0 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key max 3 R0 [6]", -2, params.getColumnPos(5)); + assertEquals("7 key max 3 R0 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 R0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [7] ___| + // [6] [5] [4] ___| + // [3] [2] <1> ___| + public void testLayout7KeyMax3R1() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R1); + assertEquals("7 key max 3 R1 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 R1 rows", 3, params.mNumRows); + assertEquals("7 key max 3 R1 left", 2, params.mLeftKeys); + assertEquals("7 key max 3 R1 right", 1, params.mRightKeys); + assertEquals("7 key max 3 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("7 key max 3 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("7 key max 3 R1 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 R1 [5]", -1, params.getColumnPos(4)); + assertEquals("7 key max 3 R1 [6]", -2, params.getColumnPos(5)); + assertEquals("7 key max 3 R1 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 R1 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [7] ___| + // [6] [4] [5] ___| + // [3] <1> [2] ___| + public void testLayout7KeyMax3R2() { + MoreKeysKeyboardParams params = createParams(7, 3, XPOS_R2); + assertEquals("7 key max 3 R2 columns", 3, params.mNumColumns); + assertEquals("7 key max 3 R2 rows", 3, params.mNumRows); + assertEquals("7 key max 3 R2 left", 1, params.mLeftKeys); + assertEquals("7 key max 3 R2 right", 2, params.mRightKeys); + assertEquals("7 key max 3 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("7 key max 3 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("7 key max 3 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("7 key max 3 R2 [4]", 0, params.getColumnPos(3)); + assertEquals("7 key max 3 R2 [5]", 1, params.getColumnPos(4)); + assertEquals("7 key max 3 R2 [6]", -1, params.getColumnPos(5)); + assertEquals("7 key max 3 R2 [7]", 0, params.getColumnPos(6)); + assertEquals("7 key max 3 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("7 key max 3 R2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [7] [5] [6] [8] + // [3] <1> [2] [4] + public void testLayout8KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_M0); + assertEquals("8 key max 5 M0 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 M0 rows", 2, params.mNumRows); + assertEquals("8 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("8 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("8 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("8 key max 5 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key max 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key max 5 M0 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // |[5] [6] [7] [8] + // |<1> [2] [3] [4] + public void testLayout8KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L0); + assertEquals("8 key max 5 L0 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 L0 rows", 2, params.mNumRows); + assertEquals("8 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("8 key max 5 L0 right", 4, params.mRightKeys); + assertEquals("8 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key max 5 L0 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 L0 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key max 5 L0 [7]", 2, params.getColumnPos(6)); + assertEquals("8 key max 5 L0 [8]", 3, params.getColumnPos(7)); + assertEquals("8 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [5] [6] [7] [8] + // |___ <1> [2] [3] [4] + public void testLayout8KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L1); + assertEquals("8 key max 5 L1 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 L1 rows", 2, params.mNumRows); + assertEquals("8 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("8 key max 5 L1 right", 4, params.mRightKeys); + assertEquals("8 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("8 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("8 key max 5 L1 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 L1 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key max 5 L1 [7]", 2, params.getColumnPos(6)); + assertEquals("8 key max 5 L1 [8]", 3, params.getColumnPos(7)); + assertEquals("8 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [7] [5] [6] [8] + // |___ [3] <1> [2] [4] + public void testLayout8KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_L2); + assertEquals("8 key max 5 L2 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 L2 rows", 2, params.mNumRows); + assertEquals("8 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("8 key max 5 L2 right", 3, params.mRightKeys); + assertEquals("8 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("8 key max 5 L2 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 L2 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key max 5 L2 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key max 5 L2 [8]", 2, params.getColumnPos(7)); + assertEquals("8 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [8] [7] [6] [5]| + // [4] [3] [2] <1>| + public void testLayout8KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R0); + assertEquals("8 key max 5 R0 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 R0 rows", 2, params.mNumRows); + assertEquals("8 key max 5 R0 left", 3, params.mLeftKeys); + assertEquals("8 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("8 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("8 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("8 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("8 key max 5 R0 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 R0 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key max 5 R0 [7]", -2, params.getColumnPos(6)); + assertEquals("8 key max 5 R0 [8]", -3, params.getColumnPos(7)); + assertEquals("8 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 R0 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [8] [7] [6] [5] ___| + // [4] [3] [2] <1> ___| + public void testLayout8KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R1); + assertEquals("8 key max 5 R1 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 R1 rows", 2, params.mNumRows); + assertEquals("8 key max 5 R1 left", 3, params.mLeftKeys); + assertEquals("8 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("8 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("8 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("8 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("8 key max 5 R1 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 R1 [6]", -1, params.getColumnPos(5)); + assertEquals("8 key max 5 R1 [7]", -2, params.getColumnPos(6)); + assertEquals("8 key max 5 R1 [8]", -3, params.getColumnPos(7)); + assertEquals("8 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 R1 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [8] [7] [5] [6] ___| + // [4] [3] <1> [2] ___| + public void testLayout8KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(8, 5, XPOS_R2); + assertEquals("8 key max 5 R2 columns", 4, params.mNumColumns); + assertEquals("8 key max 5 R2 rows", 2, params.mNumRows); + assertEquals("8 key max 5 R2 left", 2, params.mLeftKeys); + assertEquals("8 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("8 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("8 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("8 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("8 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("8 key max 5 R2 [5]", 0, params.getColumnPos(4)); + assertEquals("8 key max 5 R2 [6]", 1, params.getColumnPos(5)); + assertEquals("8 key max 5 R2 [7]", -1, params.getColumnPos(6)); + assertEquals("8 key max 5 R2 [8]", -2, params.getColumnPos(7)); + assertEquals("8 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("8 key max 5 R2 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [8] [6] [7] [9] + // [5] [3] <1> [2] [4] + public void testLayout9KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_M0); + assertEquals("9 key max 5 M0 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 M0 rows", 2, params.mNumRows); + assertEquals("9 key max 5 M0 left", 2, params.mLeftKeys); + assertEquals("9 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("9 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("9 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("9 key max 5 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("9 key max 5 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key max 5 M0 [8]", -1, params.getColumnPos(7)); + assertEquals("9 key max 5 M0 [9]", 2, params.getColumnPos(8)); + assertEquals("9 key max 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key max 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] [8] [9] + // |<1> [2] [3] [4] [5] + public void testLayout9KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L0); + assertEquals("9 key max 5 L0 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 L0 rows", 2, params.mNumRows); + assertEquals("9 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("9 key max 5 L0 right", 5, params.mRightKeys); + assertEquals("9 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("9 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("9 key max 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("9 key max 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key max 5 L0 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key max 5 L0 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] + // |___ <1> [2] [3] [4] [5] + public void testLayout9KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L1); + assertEquals("9 key max 5 L1 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 L1 rows", 2, params.mNumRows); + assertEquals("9 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("9 key max 5 L1 right", 5, params.mRightKeys); + assertEquals("9 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("9 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("9 key max 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("9 key max 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key max 5 L1 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key max 5 L1 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key max 5 L1 adjust",0, params.mTopRowAdjustment); + assertEquals("9 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] + // |___ [3] <1> [2] [4] [5] + public void testLayout9KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_L2); + assertEquals("9 key max 5 L2 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 L2 rows", 2, params.mNumRows); + assertEquals("9 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("9 key max 5 L2 right", 4, params.mRightKeys); + assertEquals("9 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("9 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("9 key max 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("9 key max 5 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key max 5 L2 [8]", 2, params.getColumnPos(7)); + assertEquals("9 key max 5 L2 [9]", 3, params.getColumnPos(8)); + assertEquals("9 key max 5 L2 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [9] [8] [7] [6]| + // [5] [4] [3] [2] <1>| + public void testLayout9KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R0); + assertEquals("9 key max 5 R0 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 R0 rows", 2, params.mNumRows); + assertEquals("9 key max 5 R0 left", 4, params.mLeftKeys); + assertEquals("9 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("9 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("9 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("9 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("9 key max 5 R0 [5]", -4, params.getColumnPos(4)); + assertEquals("9 key max 5 R0 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 R0 [7]", -1, params.getColumnPos(6)); + assertEquals("9 key max 5 R0 [8]", -2, params.getColumnPos(7)); + assertEquals("9 key max 5 R0 [9]", -3, params.getColumnPos(8)); + assertEquals("9 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key max 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [9] [8] [7] [6] ___| + // [5] [4] [3] [2] <1> ___| + public void testLayout9KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R1); + assertEquals("9 key max 5 R1 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 R1 rows", 2, params.mNumRows); + assertEquals("9 key max 5 R1 left", 4, params.mLeftKeys); + assertEquals("9 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("9 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("9 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("9 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("9 key max 5 R1 [5]", -4, params.getColumnPos(4)); + assertEquals("9 key max 5 R1 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 R1 [7]", -1, params.getColumnPos(6)); + assertEquals("9 key max 5 R1 [8]", -2, params.getColumnPos(7)); + assertEquals("9 key max 5 R1 [9]", -3, params.getColumnPos(8)); + assertEquals("9 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("9 key max 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [9] [8] [6] [7] ___| + // [5] [4] [3] <1> [2] ___| + public void testLayout9KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(9, 5, XPOS_R2); + assertEquals("9 key max 5 R2 columns", 5, params.mNumColumns); + assertEquals("9 key max 5 R2 rows", 2, params.mNumRows); + assertEquals("9 key max 5 R2 left", 3, params.mLeftKeys); + assertEquals("9 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("9 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("9 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("9 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("9 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("9 key max 5 R2 [5]", -3, params.getColumnPos(4)); + assertEquals("9 key max 5 R2 [6]", 0, params.getColumnPos(5)); + assertEquals("9 key max 5 R2 [7]", 1, params.getColumnPos(6)); + assertEquals("9 key max 5 R2 [8]", -1, params.getColumnPos(7)); + assertEquals("9 key max 5 R2 [9]", -2, params.getColumnPos(8)); + assertEquals("9 key max 5 R2 adjust", -1, params.mTopRowAdjustment); + assertEquals("9 key max 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [A] [8] [6] [7] [9] + // [5] [3] <1> [2] [4] + public void testLayout10KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_M0); + assertEquals("10 key max 5 M0 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 M0 rows", 2, params.mNumRows); + assertEquals("10 key max 5 M0 left", 2, params.mLeftKeys); + assertEquals("10 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("10 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("10 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("10 key max 5 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("10 key max 5 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key max 5 M0 [8]", -1, params.getColumnPos(7)); + assertEquals("10 key max 5 M0 [9]", 2, params.getColumnPos(8)); + assertEquals("10 key max 5 M0 [A]", -2, params.getColumnPos(9)); + assertEquals("10 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // |[6] [7] [8] [9] [A] + // |<1> [2] [3] [4] [5] + public void testLayout10KeyMax5L0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L0); + assertEquals("10 key max 5 L0 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 L0 rows", 2, params.mNumRows); + assertEquals("10 key max 5 L0 left", 0, params.mLeftKeys); + assertEquals("10 key max 5 L0 right", 5, params.mRightKeys); + assertEquals("10 key max 5 L0 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 L0 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key max 5 L0 [3]", 2, params.getColumnPos(2)); + assertEquals("10 key max 5 L0 [4]", 3, params.getColumnPos(3)); + assertEquals("10 key max 5 L0 [5]", 4, params.getColumnPos(4)); + assertEquals("10 key max 5 L0 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 L0 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key max 5 L0 [8]", 2, params.getColumnPos(7)); + assertEquals("10 key max 5 L0 [9]", 3, params.getColumnPos(8)); + assertEquals("10 key max 5 L0 [A]", 4, params.getColumnPos(9)); + assertEquals("10 key max 5 L0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 L0 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [6] [7] [8] [9] [A] + // |___ <1> [2] [3] [4] [5] + public void testLayout10KeyMax5L1() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L1); + assertEquals("10 key max 5 L1 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 L1 rows", 2, params.mNumRows); + assertEquals("10 key max 5 L1 left", 0, params.mLeftKeys); + assertEquals("10 key max 5 L1 right", 5, params.mRightKeys); + assertEquals("10 key max 5 L1 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 L1 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key max 5 L1 [3]", 2, params.getColumnPos(2)); + assertEquals("10 key max 5 L1 [4]", 3, params.getColumnPos(3)); + assertEquals("10 key max 5 L1 [5]", 4, params.getColumnPos(4)); + assertEquals("10 key max 5 L1 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 L1 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key max 5 L1 [8]", 2, params.getColumnPos(7)); + assertEquals("10 key max 5 L1 [9]", 3, params.getColumnPos(8)); + assertEquals("10 key max 5 L1 [A]", 4, params.getColumnPos(9)); + assertEquals("10 key max 5 L1 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 L1 default", WIDTH * 0, params.getDefaultKeyCoordX()); + } + + // |___ [8] [6] [7] [9] [A] + // |___ [3] <1> [2] [4] [5] + public void testLayout10KeyMax5L2() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_L2); + assertEquals("10 key max 5 L2 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 L2 rows", 2, params.mNumRows); + assertEquals("10 key max 5 L2 left", 1, params.mLeftKeys); + assertEquals("10 key max 5 L2 right", 4, params.mRightKeys); + assertEquals("10 key max 5 L2 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 L2 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key max 5 L2 [3]", -1, params.getColumnPos(2)); + assertEquals("10 key max 5 L2 [4]", 2, params.getColumnPos(3)); + assertEquals("10 key max 5 L2 [5]", 3, params.getColumnPos(4)); + assertEquals("10 key max 5 L2 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 L2 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key max 5 L2 [8]", -1, params.getColumnPos(7)); + assertEquals("10 key max 5 L2 [9]", 2, params.getColumnPos(8)); + assertEquals("10 key max 5 L2 [A]", 3, params.getColumnPos(9)); + assertEquals("10 key max 5 L2 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 L2 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [A] [9] [8] [7] [6]| + // [5] [4] [3] [2] <1>| + public void testLayout10KeyMax5R0() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R0); + assertEquals("10 key max 5 R0 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 R0 rows", 2, params.mNumRows); + assertEquals("10 key max 5 R0 left", 4, params.mLeftKeys); + assertEquals("10 key max 5 R0 right", 1, params.mRightKeys); + assertEquals("10 key max 5 R0 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 R0 [2]", -1, params.getColumnPos(1)); + assertEquals("10 key max 5 R0 [3]", -2, params.getColumnPos(2)); + assertEquals("10 key max 5 R0 [4]", -3, params.getColumnPos(3)); + assertEquals("10 key max 5 R0 [5]", -4, params.getColumnPos(4)); + assertEquals("10 key max 5 R0 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 R0 [7]", -1, params.getColumnPos(6)); + assertEquals("10 key max 5 R0 [8]", -2, params.getColumnPos(7)); + assertEquals("10 key max 5 R0 [9]", -3, params.getColumnPos(8)); + assertEquals("10 key max 5 R0 [A]", -4, params.getColumnPos(9)); + assertEquals("10 key max 5 R0 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 R0 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [A] [9] [8] [7] [6] ___| + // [5] [4] [3] [2] <1> ___| + public void testLayout10KeyMax5R1() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R1); + assertEquals("10 key max 5 R1 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 R1 rows", 2, params.mNumRows); + assertEquals("10 key max 5 R1 left", 4, params.mLeftKeys); + assertEquals("10 key max 5 R1 right", 1, params.mRightKeys); + assertEquals("10 key max 5 R1 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 R1 [2]", -1, params.getColumnPos(1)); + assertEquals("10 key max 5 R1 [3]", -2, params.getColumnPos(2)); + assertEquals("10 key max 5 R1 [4]", -3, params.getColumnPos(3)); + assertEquals("10 key max 5 R1 [5]", -4, params.getColumnPos(4)); + assertEquals("10 key max 5 R1 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 R1 [7]", -1, params.getColumnPos(6)); + assertEquals("10 key max 5 R1 [8]", -2, params.getColumnPos(7)); + assertEquals("10 key max 5 R1 [9]", -3, params.getColumnPos(8)); + assertEquals("10 key max 5 R1 [A]", -4, params.getColumnPos(9)); + assertEquals("10 key max 5 R1 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 R1 default", WIDTH * 4, params.getDefaultKeyCoordX()); + } + + // [A] [9] [8] [6] [7] ___| + // [5] [4] [3] <1> [2] ___| + public void testLayout10KeyMax5R2() { + MoreKeysKeyboardParams params = createParams(10, 5, XPOS_R2); + assertEquals("10 key max 5 R2 columns", 5, params.mNumColumns); + assertEquals("10 key max 5 R2 rows", 2, params.mNumRows); + assertEquals("10 key max 5 R2 left", 3, params.mLeftKeys); + assertEquals("10 key max 5 R2 right", 2, params.mRightKeys); + assertEquals("10 key max 5 R2 <1>", 0, params.getColumnPos(0)); + assertEquals("10 key max 5 R2 [2]", 1, params.getColumnPos(1)); + assertEquals("10 key max 5 R2 [3]", -1, params.getColumnPos(2)); + assertEquals("10 key max 5 R2 [4]", -2, params.getColumnPos(3)); + assertEquals("10 key max 5 R2 [5]", -3, params.getColumnPos(4)); + assertEquals("10 key max 5 R2 [6]", 0, params.getColumnPos(5)); + assertEquals("10 key max 5 R2 [7]", 1, params.getColumnPos(6)); + assertEquals("10 key max 5 R2 [8]", -1, params.getColumnPos(7)); + assertEquals("10 key max 5 R2 [9]", -2, params.getColumnPos(8)); + assertEquals("10 key max 5 R2 [A]", -3, params.getColumnPos(9)); + assertEquals("10 key max 5 R2 adjust", 0, params.mTopRowAdjustment); + assertEquals("10 key max 5 R2 default", WIDTH * 3, params.getDefaultKeyCoordX()); + } + + // [9] [A] [B] + // [7] [5] [6] [8] + // [3] <1> [2] [4] + public void testLayout11KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(11, 5, XPOS_M0); + assertEquals("11 key max 5 M0 columns", 4, params.mNumColumns); + assertEquals("11 key max 5 M0 rows", 3, params.mNumRows); + assertEquals("11 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("11 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("11 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("11 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("11 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("11 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("11 key max 5 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("11 key max 5 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("11 key max 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("11 key max 5 M0 [8]", 2, params.getColumnPos(7)); + assertEquals("11 key max 5 M0 [9]", 0, params.getColumnPos(8)); + assertEquals("11 key max 5 M0 [A]", 1, params.getColumnPos(9)); + assertEquals("11 key max 5 M0 [B]", 2, params.getColumnPos(10)); + assertEquals("11 key max 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("11 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [B] [9] [A] [C] + // [7] [5] [6] [8] + // [3] <1> [2] [4] + public void testLayout12KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(12, 5, XPOS_M0); + assertEquals("12 key max 5 M0 columns", 4, params.mNumColumns); + assertEquals("12 key max 5 M0 rows", 3, params.mNumRows); + assertEquals("12 key max 5 M0 left", 1, params.mLeftKeys); + assertEquals("12 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("12 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("12 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("12 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("12 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("12 key max 5 M0 [5]", 0, params.getColumnPos(4)); + assertEquals("12 key max 5 M0 [6]", 1, params.getColumnPos(5)); + assertEquals("12 key max 5 M0 [7]", -1, params.getColumnPos(6)); + assertEquals("12 key max 5 M0 [8]", 2, params.getColumnPos(7)); + assertEquals("12 key max 5 M0 [9]", 0, params.getColumnPos(8)); + assertEquals("12 key max 5 M0 [A]", 1, params.getColumnPos(9)); + assertEquals("12 key max 5 M0 [B]", -1, params.getColumnPos(10)); + assertEquals("12 key max 5 M0 [C]", 2, params.getColumnPos(11)); + assertEquals("12 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("12 key max 5 M0 default", WIDTH * 1, params.getDefaultKeyCoordX()); + } + + // [D] [B] [C] + // [A] [8] [6] [7] [9] + // [5] [3] <1> [2] [4] + public void testLayout13KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(13, 5, XPOS_M0); + assertEquals("13 key max 5 M0 columns", 5, params.mNumColumns); + assertEquals("13 key max 5 M0 rows", 3, params.mNumRows); + assertEquals("13 key max 5 M0 left", 2, params.mLeftKeys); + assertEquals("13 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("13 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("13 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("13 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("13 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("13 key max 5 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("13 key max 5 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("13 key max 5 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("13 key max 5 M0 [8]", -1, params.getColumnPos(7)); + assertEquals("13 key max 5 M0 [9]", 2, params.getColumnPos(8)); + assertEquals("13 key max 5 M0 [A]", -2, params.getColumnPos(9)); + assertEquals("13 key max 5 M0 [B]", 0, params.getColumnPos(10)); + assertEquals("13 key max 5 M0 [C]", 1, params.getColumnPos(11)); + assertEquals("13 key max 5 M0 [D]", -1, params.getColumnPos(12)); + assertEquals("13 key max 5 M0 adjust", 0, params.mTopRowAdjustment); + assertEquals("13 key max 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } + + // [D] [B] [C] [E] + // [A] [8] [6] [7] [9] + // [5] [3] <1> [2] [4] + public void testLayout14KeyMax5M0() { + MoreKeysKeyboardParams params = createParams(14, 5, XPOS_M0); + assertEquals("13 key max 5 M0 columns", 5, params.mNumColumns); + assertEquals("13 key max 5 M0 rows", 3, params.mNumRows); + assertEquals("13 key max 5 M0 left", 2, params.mLeftKeys); + assertEquals("13 key max 5 M0 right", 3, params.mRightKeys); + assertEquals("13 key max 5 M0 <1>", 0, params.getColumnPos(0)); + assertEquals("13 key max 5 M0 [2]", 1, params.getColumnPos(1)); + assertEquals("13 key max 5 M0 [3]", -1, params.getColumnPos(2)); + assertEquals("13 key max 5 M0 [4]", 2, params.getColumnPos(3)); + assertEquals("13 key max 5 M0 [5]", -2, params.getColumnPos(4)); + assertEquals("13 key max 5 M0 [6]", 0, params.getColumnPos(5)); + assertEquals("13 key max 5 M0 [7]", 1, params.getColumnPos(6)); + assertEquals("13 key max 5 M0 [8]", -1, params.getColumnPos(7)); + assertEquals("13 key max 5 M0 [9]", 2, params.getColumnPos(8)); + assertEquals("13 key max 5 M0 [A]", -2, params.getColumnPos(9)); + assertEquals("13 key max 5 M0 [B]", 0, params.getColumnPos(10)); + assertEquals("13 key max 5 M0 [C]", 1, params.getColumnPos(11)); + assertEquals("13 key max 5 M0 [D]", -1, params.getColumnPos(12)); + assertEquals("13 key max 5 M0 [E]", 2, params.getColumnPos(13)); + assertEquals("13 key max 5 M0 adjust", -1, params.mTopRowAdjustment); + assertEquals("13 key max 5 M0 default", WIDTH * 2, params.getDefaultKeyCoordX()); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java new file mode 100644 index 000000000..e090031e4 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserCsvTests.java @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.text.TextUtils; + +import com.android.inputmethod.latin.tests.R; + +import java.util.Arrays; + +public class KeySpecParserCsvTests extends AndroidTestCase { + private Resources mTestResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mTestResources = getTestContext().getResources(); + } + + private static String format(String message, Object expected, Object actual) { + return message + " expected:<" + expected + "> but was:<" + actual + ">"; + } + + private void assertTextArray(String message, String value, String ... expected) { + final String actual[] = KeySpecParser.parseCsvString(value, mTestResources, + R.string.empty_string); + if (expected.length == 0) { + assertNull(message + ": expected=null actual=" + Arrays.toString(actual), + actual); + return; + } + assertEquals(message + ": expected=" + Arrays.toString(expected) + + " actual=" + Arrays.toString(actual) + + ": result length", expected.length, actual.length); + for (int i = 0; i < actual.length; i++) { + final boolean equals = TextUtils.equals(expected[i], actual[i]); + assertTrue(format(message + ": result at " + i + ":", expected[i], actual[i]), equals); + } + } + + private void assertError(String message, String value, String ... expected) { + try { + assertTextArray(message, value, expected); + fail(message); + } catch (Exception pcpe) { + // success. + } + } + + // \U001d11e: MUSICAL SYMBOL G CLEF + private static final String PAIR1 = "\ud834\udd1e"; + // \U001d122: MUSICAL SYMBOL F CLEF + private static final String PAIR2 = "\ud834\udd22"; + // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. + private static final String PAIR3 = "\ud87e\udca6"; + private static final String SURROGATE1 = PAIR1 + PAIR2; + private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; + + public void testParseCsvTextZero() { + assertTextArray("Empty string", ""); + assertTextArray("Empty entry", ","); + assertTextArray("Empty entry at beginning", ",a", "a"); + assertTextArray("Empty entry at end", "a,", "a"); + assertTextArray("Empty entry at middle", "a,,b", "a", "b"); + assertTextArray("Empty entries with escape", ",a,b\\,c,,d,", "a", "b\\,c", "d"); + } + + public void testParseCsvTextSingle() { + assertTextArray("Single char", "a", "a"); + assertTextArray("Surrogate pair", PAIR1, PAIR1); + assertTextArray("Single escape", "\\", "\\"); + assertTextArray("Space", " ", " "); + assertTextArray("Single label", "abc", "abc"); + assertTextArray("Single surrogate pairs label", SURROGATE2, SURROGATE2); + assertTextArray("Spaces", " ", " "); + assertTextArray("Spaces in label", "a b c", "a b c"); + assertTextArray("Spaces at beginning of label", " abc", " abc"); + assertTextArray("Spaces at end of label", "abc ", "abc "); + assertTextArray("Label surrounded by spaces", " abc ", " abc "); + assertTextArray("Surrogate pair surrounded by space", + " " + PAIR1 + " ", + " " + PAIR1 + " "); + assertTextArray("Surrogate pair within characters", + "ab" + PAIR2 + "cd", + "ab" + PAIR2 + "cd"); + assertTextArray("Surrogate pairs within characters", + "ab" + SURROGATE1 + "cd", + "ab" + SURROGATE1 + "cd"); + + assertTextArray("Incomplete resource reference 1", "string", "string"); + assertTextArray("Incomplete resource reference 2", "@string", "@string"); + assertTextArray("Incomplete resource reference 3", "string/", "string/"); + assertTextArray("Incomplete resource reference 4", "@" + SURROGATE2, "@" + SURROGATE2); + } + + public void testParseCsvTextSingleEscaped() { + assertTextArray("Escaped char", "\\a", "\\a"); + assertTextArray("Escaped surrogate pair", "\\" + PAIR1, "\\" + PAIR1); + assertTextArray("Escaped comma", "\\,", "\\,"); + assertTextArray("Escaped comma escape", "a\\,\\", "a\\,\\"); + assertTextArray("Escaped escape", "\\\\", "\\\\"); + assertTextArray("Escaped label", "a\\bc", "a\\bc"); + assertTextArray("Escaped surrogate", "a\\" + PAIR1 + "c", "a\\" + PAIR1 + "c"); + assertTextArray("Escaped label at beginning", "\\abc", "\\abc"); + assertTextArray("Escaped surrogate at beginning", "\\" + SURROGATE2, "\\" + SURROGATE2); + assertTextArray("Escaped label at end", "abc\\", "abc\\"); + assertTextArray("Escaped surrogate at end", SURROGATE2 + "\\", SURROGATE2 + "\\"); + assertTextArray("Escaped label with comma", "a\\,c", "a\\,c"); + assertTextArray("Escaped surrogate with comma", + PAIR1 + "\\," + PAIR2, PAIR1 + "\\," + PAIR2); + assertTextArray("Escaped label with comma at beginning", "\\,bc", "\\,bc"); + assertTextArray("Escaped surrogate with comma at beginning", + "\\," + SURROGATE1, "\\," + SURROGATE1); + assertTextArray("Escaped label with comma at end", "ab\\,", "ab\\,"); + assertTextArray("Escaped surrogate with comma at end", + SURROGATE2 + "\\,", SURROGATE2 + "\\,"); + assertTextArray("Escaped label with successive", "\\,\\\\bc", "\\,\\\\bc"); + assertTextArray("Escaped surrogate with successive", + "\\,\\\\" + SURROGATE1, "\\,\\\\" + SURROGATE1); + assertTextArray("Escaped label with escape", "a\\\\c", "a\\\\c"); + assertTextArray("Escaped surrogate with escape", + PAIR1 + "\\\\" + PAIR2, PAIR1 + "\\\\" + PAIR2); + + assertTextArray("Escaped @string", "\\@string", "\\@string"); + assertTextArray("Escaped @string/", "\\@string/", "\\@string/"); + assertTextArray("Escaped @string/", "\\@string/empty_string", "\\@string/empty_string"); + } + + public void testParseCsvTextMulti() { + assertTextArray("Multiple chars", "a,b,c", "a", "b", "c"); + assertTextArray("Multiple chars", "a,b,\\c", "a", "b", "\\c"); + assertTextArray("Multiple chars and escape at beginning and end", + "\\a,b,\\c\\", "\\a", "b", "\\c\\"); + assertTextArray("Multiple surrogates", PAIR1 + "," + PAIR2 + "," + PAIR3, + PAIR1, PAIR2, PAIR3); + assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c "); + assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi"); + assertTextArray("Multiple surrogated", SURROGATE1 + "," + SURROGATE2, + SURROGATE1, SURROGATE2); + assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ", + " abc ", " def ", " ghi "); + } + + public void testParseCsvTextMultiEscaped() { + assertTextArray("Multiple chars with comma", "a,\\,,c", "a", "\\,", "c"); + assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ", + " a ", " \\, ", " c "); + assertTextArray("Multiple labels with escape", + "\\abc,d\\ef,gh\\i", "\\abc", "d\\ef", "gh\\i"); + assertTextArray("Multiple labels with escape surrounded by spaces", + " \\abc , d\\ef , gh\\i ", " \\abc ", " d\\ef ", " gh\\i "); + assertTextArray("Multiple labels with comma and escape", + "ab\\\\,d\\\\\\,,g\\,i", "ab\\\\", "d\\\\\\,", "g\\,i"); + assertTextArray("Multiple labels with comma and escape surrounded by spaces", + " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\\\ ", " d\\\\\\, ", " g\\,i "); + + assertTextArray("Multiple escaped @string", "\\@,\\@string/empty_string", + "\\@", "\\@string/empty_string"); + } + + public void testParseCsvResourceError() { + assertError("Incomplete resource name", "@string/", "@string/"); + assertError("Non existing resource", "@string/non_existing"); + } + + public void testParseCsvResourceZero() { + assertTextArray("Empty string", + "@string/empty_string"); + } + + public void testParseCsvResourceSingle() { + assertTextArray("Single char", + "@string/single_char", "a"); + assertTextArray("Space", + "@string/space", " "); + assertTextArray("Single label", + "@string/single_label", "abc"); + assertTextArray("Spaces", + "@string/spaces", " "); + assertTextArray("Spaces in label", + "@string/spaces_in_label", "a b c"); + assertTextArray("Spaces at beginning of label", + "@string/spaces_at_beginning_of_label", " abc"); + assertTextArray("Spaces at end of label", + "@string/spaces_at_end_of_label", "abc "); + assertTextArray("label surrounded by spaces", + "@string/label_surrounded_by_spaces", " abc "); + + assertTextArray("Escape and single char", + "\\\\@string/single_char", "\\\\a"); + } + + public void testParseCsvResourceSingleEscaped() { + assertTextArray("Escaped char", + "@string/escaped_char", "\\a"); + assertTextArray("Escaped comma", + "@string/escaped_comma", "\\,"); + assertTextArray("Escaped comma escape", + "@string/escaped_comma_escape", "a\\,\\"); + assertTextArray("Escaped escape", + "@string/escaped_escape", "\\\\"); + assertTextArray("Escaped label", + "@string/escaped_label", "a\\bc"); + assertTextArray("Escaped label at beginning", + "@string/escaped_label_at_beginning", "\\abc"); + assertTextArray("Escaped label at end", + "@string/escaped_label_at_end", "abc\\"); + assertTextArray("Escaped label with comma", + "@string/escaped_label_with_comma", "a\\,c"); + assertTextArray("Escaped label with comma at beginning", + "@string/escaped_label_with_comma_at_beginning", "\\,bc"); + assertTextArray("Escaped label with comma at end", + "@string/escaped_label_with_comma_at_end", "ab\\,"); + assertTextArray("Escaped label with successive", + "@string/escaped_label_with_successive", "\\,\\\\bc"); + assertTextArray("Escaped label with escape", + "@string/escaped_label_with_escape", "a\\\\c"); + } + + public void testParseCsvResourceMulti() { + assertTextArray("Multiple chars", + "@string/multiple_chars", "a", "b", "c"); + assertTextArray("Multiple chars surrounded by spaces", + "@string/multiple_chars_surrounded_by_spaces", + " a ", " b ", " c "); + assertTextArray("Multiple labels", + "@string/multiple_labels", "abc", "def", "ghi"); + assertTextArray("Multiple labels surrounded by spaces", + "@string/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi "); + } + + public void testParseCsvResourcetMultiEscaped() { + assertTextArray("Multiple chars with comma", + "@string/multiple_chars_with_comma", + "a", "\\,", "c"); + assertTextArray("Multiple chars with comma surrounded by spaces", + "@string/multiple_chars_with_comma_surrounded_by_spaces", + " a ", " \\, ", " c "); + assertTextArray("Multiple labels with escape", + "@string/multiple_labels_with_escape", + "\\abc", "d\\ef", "gh\\i"); + assertTextArray("Multiple labels with escape surrounded by spaces", + "@string/multiple_labels_with_escape_surrounded_by_spaces", + " \\abc ", " d\\ef ", " gh\\i "); + assertTextArray("Multiple labels with comma and escape", + "@string/multiple_labels_with_comma_and_escape", + "ab\\\\", "d\\\\\\,", "g\\,i"); + assertTextArray("Multiple labels with comma and escape surrounded by spaces", + "@string/multiple_labels_with_comma_and_escape_surrounded_by_spaces", + " ab\\\\ ", " d\\\\\\, ", " g\\,i "); + } + + public void testParseMultipleResources() { + assertTextArray("Literals and resources", + "1,@string/multiple_chars,z", "1", "a", "b", "c", "z"); + assertTextArray("Literals and resources and escape at end", + "\\1,@string/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\"); + assertTextArray("Multiple single resource chars and labels", + "@string/single_char,@string/single_label,@string/escaped_comma", + "a", "abc", "\\,"); + assertTextArray("Multiple single resource chars and labels 2", + "@string/single_char,@string/single_label,@string/escaped_comma_escape", + "a", "abc", "a\\,\\"); + assertTextArray("Multiple multiple resource chars and labels", + "@string/multiple_chars,@string/multiple_labels,@string/multiple_chars_with_comma", + "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c"); + assertTextArray("Concatenated resources", + "@string/multiple_chars@string/multiple_labels@string/multiple_chars_with_comma", + "a", "b", "cabc", "def", "ghia", "\\,", "c"); + assertTextArray("Concatenated resource and literal", + "abc@string/multiple_labels", + "abcabc", "def", "ghi"); + } + + public void testParseIndirectReference() { + assertTextArray("Indirect", + "@string/indirect_string", "a", "b", "c"); + assertTextArray("Indirect with literal", + "1,@string/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2"); + } + + public void testParseInfiniteIndirectReference() { + assertError("Infinite indirection", + "1,@string/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2"); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java new file mode 100644 index 000000000..3fc2b021a --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.res.Resources; +import android.test.AndroidTestCase; + +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.R; + +import java.util.Arrays; + +public class KeySpecParserTests extends AndroidTestCase { + private Resources mRes; + + private static final int ICON_UNDEFINED = KeyboardIconsSet.ICON_UNDEFINED; + + private static final String CODE_SETTINGS_RES = "integer/key_settings"; + private static final String ICON_SETTINGS_NAME = "settingsKey"; + + private static final String CODE_SETTINGS = "@" + CODE_SETTINGS_RES; + private static final String ICON_SETTINGS = "@icon/" + ICON_SETTINGS_NAME; + private static final String CODE_NON_EXISTING = "@integer/non_existing"; + private static final String ICON_NON_EXISTING = "@icon/non_existing"; + + private int mCodeSettings; + private int mSettingsIconId; + + @Override + protected void setUp() { + Resources res = getContext().getResources(); + mRes = res; + + final String packageName = res.getResourcePackageName(R.string.english_ime_name); + final int codeId = res.getIdentifier(CODE_SETTINGS_RES, null, packageName); + mCodeSettings = res.getInteger(codeId); + mSettingsIconId = KeyboardIconsSet.getIconId(ICON_SETTINGS_NAME); + } + + private void assertParser(String message, String moreKeySpec, String expectedLabel, + String expectedOutputText, int expectedIcon, int expectedCode) { + String actualLabel = KeySpecParser.getLabel(moreKeySpec); + assertEquals(message + ": label:", expectedLabel, actualLabel); + + String actualOutputText = KeySpecParser.getOutputText(moreKeySpec); + assertEquals(message + ": ouptputText:", expectedOutputText, actualOutputText); + + int actualIcon = KeySpecParser.getIconId(moreKeySpec); + assertEquals(message + ": icon:", expectedIcon, actualIcon); + + int actualCode = KeySpecParser.getCode(mRes, moreKeySpec); + assertEquals(message + ": codes value:", expectedCode, actualCode); + } + + private void assertParserError(String message, String moreKeySpec, String expectedLabel, + String expectedOutputText, int expectedIcon, int expectedCode) { + try { + assertParser(message, moreKeySpec, expectedLabel, expectedOutputText, expectedIcon, + expectedCode); + fail(message); + } catch (Exception pcpe) { + // success. + } + } + + // \U001d11e: MUSICAL SYMBOL G CLEF + private static final String PAIR1 = "\ud834\udd1e"; + private static final int CODE1 = PAIR1.codePointAt(0); + // \U001d122: MUSICAL SYMBOL F CLEF + private static final String PAIR2 = "\ud834\udd22"; + private static final int CODE2 = PAIR2.codePointAt(0); + // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. + private static final String PAIR3 = "\ud87e\udca6"; + private static final String SURROGATE1 = PAIR1 + PAIR2; + private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; + + public void testSingleLetter() { + assertParser("Single letter", "a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single surrogate", PAIR1, + PAIR1, null, ICON_UNDEFINED, CODE1); + assertParser("Single escaped bar", "\\|", + "|", null, ICON_UNDEFINED, '|'); + assertParser("Single escaped escape", "\\\\", + "\\", null, ICON_UNDEFINED, '\\'); + assertParser("Single comma", ",", + ",", null, ICON_UNDEFINED, ','); + assertParser("Single escaped comma", "\\,", + ",", null, ICON_UNDEFINED, ','); + assertParser("Single escaped letter", "\\a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single escaped surrogate", "\\" + PAIR2, + PAIR2, null, ICON_UNDEFINED, CODE2); + assertParser("Single at", "@", + "@", null, ICON_UNDEFINED, '@'); + assertParser("Single escaped at", "\\@", + "@", null, ICON_UNDEFINED, '@'); + assertParser("Single output text letter", "a|a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single surrogate pair outputText", "G Clef|" + PAIR1, + "G Clef", null, ICON_UNDEFINED, CODE1); + assertParser("Single letter with outputText", "a|abc", + "a", "abc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with surrogate outputText", "a|" + SURROGATE1, + "a", SURROGATE1, ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single surrogate with outputText", PAIR3 + "|abc", + PAIR3, "abc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped outputText", "a|a\\|c", + "a", "a|c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped surrogate outputText", + "a|" + PAIR1 + "\\|" + PAIR2, + "a", PAIR1 + "|" + PAIR2, ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with comma outputText", "a|a,b", + "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped comma outputText", "a|a\\,b", + "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with outputText starts with at", "a|@bc", + "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with surrogate outputText starts with at", "a|@" + SURROGATE2, + "a", "@" + SURROGATE2, ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with outputText contains at", "a|a@c", + "a", "a@c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped at outputText", "a|\\@bc", + "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Single escaped escape with single outputText", "\\\\|\\\\", + "\\", null, ICON_UNDEFINED, '\\'); + assertParser("Single escaped bar with single outputText", "\\||\\|", + "|", null, ICON_UNDEFINED, '|'); + assertParser("Single letter with code", "a|" + CODE_SETTINGS, + "a", null, ICON_UNDEFINED, mCodeSettings); + } + + public void testLabel() { + assertParser("Simple label", "abc", + "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Simple surrogate label", SURROGATE1, + SURROGATE1, SURROGATE1, ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar", "a\\|c", + "a|c", "a|c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Surrogate label with escaped bar", PAIR1 + "\\|" + PAIR2, + PAIR1 + "|" + PAIR2, PAIR1 + "|" + PAIR2, + ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped escape", "a\\\\c", + "a\\c", "a\\c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with comma", "a,c", + "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped comma", "a\\,c", + "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label starts with at", "@bc", + "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Surrogate label starts with at", "@" + SURROGATE1, + "@" + SURROGATE1, "@" + SURROGATE1, ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label contains at", "a@c", + "a@c", "a@c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped at", "\\@bc", + "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped letter", "\\abc", + "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with outputText", "abc|def", + "abc", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with comma and outputText", "a,c|def", + "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Escaped comma label with outputText", "a\\,c|def", + "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Escaped label with outputText", "a\\|c|def", + "a|c", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar outputText", "abc|d\\|f", + "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Escaped escape label with outputText", "a\\\\|def", + "a\\", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label starts with at and outputText", "@bc|def", + "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label contains at label and outputText", "a@c|def", + "a@c", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Escaped at label with outputText", "\\@bc|def", + "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with comma outputText", "abc|a,b", + "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped comma outputText", "abc|a\\,b", + "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with outputText starts with at", "abc|@bc", + "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with outputText contains at", "abc|a@c", + "abc", "a@c", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped at outputText", "abc|\\@bc", + "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar outputText", "abc|d\\|f", + "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Escaped bar label with escaped bar outputText", "a\\|c|d\\|f", + "a|c", "d|f", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label with code", "abc|" + CODE_SETTINGS, + "abc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS, + "a|c", null, ICON_UNDEFINED, mCodeSettings); + } + + public void testIconAndCode() { + assertParser("Icon with outputText", ICON_SETTINGS + "|abc", + null, "abc", mSettingsIconId, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Icon with outputText starts with at", ICON_SETTINGS + "|@bc", + null, "@bc", mSettingsIconId, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Icon with outputText contains at", ICON_SETTINGS + "|a@c", + null, "a@c", mSettingsIconId, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Icon with escaped at outputText", ICON_SETTINGS + "|\\@bc", + null, "@bc", mSettingsIconId, Keyboard.CODE_OUTPUT_TEXT); + assertParser("Label starts with at and code", "@bc|" + CODE_SETTINGS, + "@bc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Label contains at and code", "a@c|" + CODE_SETTINGS, + "a@c", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Escaped at label with code", "\\@bc|" + CODE_SETTINGS, + "@bc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS, + null, null, mSettingsIconId, mCodeSettings); + } + + public void testFormatError() { + assertParserError("Empty spec", "", null, + null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Empty label with outputText", "|a", + null, "a", ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Empty label with code", "|" + CODE_SETTINGS, + null, null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Empty outputText with label", "a|", + "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Empty outputText with icon", ICON_SETTINGS + "|", + null, null, mSettingsIconId, Keyboard.CODE_UNSPECIFIED); + assertParserError("Empty icon and code", "|", + null, null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Icon without code", ICON_SETTINGS, + null, null, mSettingsIconId, Keyboard.CODE_UNSPECIFIED); + assertParserError("Non existing icon", ICON_NON_EXISTING + "|abc", + null, "abc", ICON_UNDEFINED, Keyboard.CODE_OUTPUT_TEXT); + assertParserError("Non existing code", "abc|" + CODE_NON_EXISTING, + "abc", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Third bar at end", "a|b|", + "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Multiple bar", "a|b|c", + "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); + assertParserError("Multiple bar with label and code", "a|" + CODE_SETTINGS + "|c", + "a", null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Multiple bar with icon and outputText", ICON_SETTINGS + "|b|c", + null, null, mSettingsIconId, Keyboard.CODE_UNSPECIFIED); + assertParserError("Multiple bar with icon and code", + ICON_SETTINGS + "|" + CODE_SETTINGS + "|c", + null, null, mSettingsIconId, mCodeSettings); + } + + private static void assertMoreKeys(String message, String[] moreKeys, + String[] additionalMoreKeys, String[] expected) { + final String[] actual = KeySpecParser.insertAddtionalMoreKeys( + moreKeys, additionalMoreKeys); + if (expected == null && actual == null) { + return; + } + if (expected == null || actual == null) { + assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); + } else { + if (expected.length != actual.length) { + assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); + } + for (int i = 0; i < expected.length; i++) { + if (!actual[i].equals(expected[i])) { + assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); + } + } + } + } + + public void testEmptyEntry() { + assertMoreKeys("null more keys and null additons", + null, + null, + null); + assertMoreKeys("null more keys and empty additons", + null, + new String[0], + null); + assertMoreKeys("empty more keys and null additons", + new String[0], + null, + null); + assertMoreKeys("empty more keys and empty additons", + new String[0], + new String[0], + null); + + assertMoreKeys("filter out empty more keys", + new String[] { null, "a", "", "b", null }, + null, + new String[] { "a", "b" }); + assertMoreKeys("filter out empty additons", + new String[] { "a", "%", "b", "%", "c", "%", "d" }, + new String[] { null, "A", "", "B", null }, + new String[] { "a", "A", "b", "B", "c", "d" }); + } + + public void testInsertAdditionalMoreKeys() { + // Escaped marker. + assertMoreKeys("escaped marker", + new String[] { "\\%", "%-)" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "\\%", "%-)" }); + + // 0 more key. + assertMoreKeys("null & null", null, null, null); + assertMoreKeys("null & 1 additon", + null, + new String[] { "1" }, + new String[] { "1" }); + assertMoreKeys("null & 2 additons", + null, + new String[] { "1", "2" }, + new String[] { "1", "2" }); + + // 0 additional more key. + assertMoreKeys("1 more key & null", + new String[] { "A" }, + null, + new String[] { "A" }); + assertMoreKeys("2 more keys & null", + new String[] { "A", "B" }, + null, + new String[] { "A", "B" }); + + // No marker. + assertMoreKeys("1 more key & 1 addtional & no marker", + new String[] { "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertMoreKeys("1 more key & 2 addtionals & no marker", + new String[] { "A" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A" }); + assertMoreKeys("2 more keys & 1 addtional & no marker", + new String[] { "A", "B" }, + new String[] { "1" }, + new String[] { "1", "A", "B" }); + assertMoreKeys("2 more keys & 2 addtionals & no marker", + new String[] { "A", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A", "B" }); + + // 1 marker. + assertMoreKeys("1 more key & 1 additon & marker at head", + new String[] { "%", "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertMoreKeys("1 more key & 1 additon & marker at tail", + new String[] { "A", "%" }, + new String[] { "1" }, + new String[] { "A", "1" }); + assertMoreKeys("2 more keys & 1 additon & marker at middle", + new String[] { "A", "%", "B" }, + new String[] { "1" }, + new String[] { "A", "1", "B" }); + + // 1 marker & excess additional more keys. + assertMoreKeys("1 more key & 2 additons & marker at head", + new String[] { "%", "A", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "B", "2" }); + assertMoreKeys("1 more key & 2 additons & marker at tail", + new String[] { "A", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "B", "1", "2" }); + assertMoreKeys("2 more keys & 2 additons & marker at middle", + new String[] { "A", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "B", "2" }); + + // 2 markers. + assertMoreKeys("0 more key & 2 addtional & 2 markers", + new String[] { "%", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "2" }); + assertMoreKeys("1 more key & 2 addtional & 2 markers at head", + new String[] { "%", "%", "A" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A" }); + assertMoreKeys("1 more key & 2 addtional & 2 markers at tail", + new String[] { "A", "%", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "2" }); + assertMoreKeys("2 more keys & 2 addtional & 2 markers at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "2", "B" }); + assertMoreKeys("2 more keys & 2 addtional & 2 markers at head & middle", + new String[] { "%", "A", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "2", "B" }); + assertMoreKeys("2 more keys & 2 addtional & 2 markers at head & tail", + new String[] { "%", "A", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "B", "2" }); + assertMoreKeys("2 more keys & 2 addtional & 2 markers at middle & tail", + new String[] { "A", "%", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "B", "2" }); + + // 2 markers & excess additional more keys. + assertMoreKeys("0 more key & 2 additons & 2 markers", + new String[] { "%", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "2", "3" }); + assertMoreKeys("1 more key & 2 additons & 2 markers at head", + new String[] { "%", "%", "A" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "2", "A", "3" }); + assertMoreKeys("1 more key & 2 additons & 2 markers at tail", + new String[] { "A", "%", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "2", "3" }); + assertMoreKeys("2 more keys & 2 additons & 2 markers at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "2", "B", "3" }); + assertMoreKeys("2 more keys & 2 additons & 2 markers at head & middle", + new String[] { "%", "A", "%", "B" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "2", "B", "3" }); + assertMoreKeys("2 more keys & 2 additons & 2 markers at head & tail", + new String[] { "%", "A", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "B", "2", "3" }); + assertMoreKeys("2 more keys & 2 additons & 2 markers at middle & tail", + new String[] { "A", "%", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "B", "2", "3" }); + + // 0 addtional more key and excess markers. + assertMoreKeys("0 more key & null & excess marker", + new String[] { "%" }, + null, + null); + assertMoreKeys("1 more key & null & excess marker at head", + new String[] { "%", "A" }, + null, + new String[] { "A" }); + assertMoreKeys("1 more key & null & excess marker at tail", + new String[] { "A", "%" }, + null, + new String[] { "A" }); + assertMoreKeys("2 more keys & null & excess marker at middle", + new String[] { "A", "%", "B" }, + null, + new String[] { "A", "B" }); + assertMoreKeys("2 more keys & null & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + null, + new String[] { "A", "B" }); + + // Excess markers. + assertMoreKeys("0 more key & 1 additon & excess marker", + new String[] { "%", "%" }, + new String[] { "1" }, + new String[] { "1" }); + assertMoreKeys("1 more key & 1 additon & excess marker at head", + new String[] { "%", "%", "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertMoreKeys("1 more key & 1 additon & excess marker at tail", + new String[] { "A", "%", "%" }, + new String[] { "1" }, + new String[] { "A", "1" }); + assertMoreKeys("2 more keys & 1 additon & excess marker at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1" }, + new String[] { "A", "1", "B" }); + assertMoreKeys("2 more keys & 1 additon & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + new String[] { "1" }, + new String[] { "1", "A", "B" }); + assertMoreKeys("2 more keys & 2 additons & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "2", "B" }); + assertMoreKeys("2 more keys & 3 additons & excess markers", + new String[] { "%", "A", "%", "%", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "2", "3", "B" }); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java deleted file mode 100644 index 4050a7123..000000000 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import com.android.inputmethod.keyboard.internal.KeyStyles.EmptyKeyStyle; - -import android.test.AndroidTestCase; -import android.text.TextUtils; - -public class KeyStylesTests extends AndroidTestCase { - private static String format(String message, Object expected, Object actual) { - return message + " expected:<" + expected + "> but was:<" + actual + ">"; - } - - private static void assertTextArray(String message, CharSequence value, - CharSequence ... expected) { - final CharSequence actual[] = EmptyKeyStyle.parseCsvText(value); - if (expected.length == 0) { - assertNull(message, actual); - return; - } - assertSame(message + ": result length", expected.length, actual.length); - for (int i = 0; i < actual.length; i++) { - final boolean equals = TextUtils.equals(expected[i], actual[i]); - assertTrue(format(message + ": result at " + i + ":", expected[i], actual[i]), equals); - } - } - - public void testParseCsvTextZero() { - assertTextArray("Empty string", ""); - } - - public void testParseCsvTextSingle() { - assertTextArray("Single char", "a", "a"); - assertTextArray("Space", " ", " "); - assertTextArray("Single label", "abc", "abc"); - assertTextArray("Spaces", " ", " "); - assertTextArray("Spaces in label", "a b c", "a b c"); - assertTextArray("Spaces at beginning of label", " abc", " abc"); - assertTextArray("Spaces at end of label", "abc ", "abc "); - assertTextArray("label surrounded by spaces", " abc ", " abc "); - } - - public void testParseCsvTextSingleEscaped() { - assertTextArray("Escaped char", "\\a", "a"); - assertTextArray("Escaped comma", "\\,", ","); - assertTextArray("Escaped escape", "\\\\", "\\"); - assertTextArray("Escaped label", "a\\bc", "abc"); - assertTextArray("Escaped label at begininng", "\\abc", "abc"); - assertTextArray("Escaped label with comma", "a\\,c", "a,c"); - assertTextArray("Escaped label with comma at beginning", "\\,bc", ",bc"); - assertTextArray("Escaped label with successive", "\\,\\\\bc", ",\\bc"); - assertTextArray("Escaped label with escape", "a\\\\c", "a\\c"); - } - - public void testParseCsvTextMulti() { - assertTextArray("Multiple chars", "a,b,c", "a", "b", "c"); - assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c "); - assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi"); - assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ", - " abc ", " def ", " ghi "); - } - - public void testParseCsvTextMultiEscaped() { - assertTextArray("Multiple chars with comma", "a,\\,,c", "a", ",", "c"); - assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ", - " a ", " , ", " c "); - assertTextArray("Multiple labels with escape", "\\abc,d\\ef,gh\\i", "abc", "def", "ghi"); - assertTextArray("Multiple labels with escape surrounded by spaces", - " \\abc , d\\ef , gh\\i ", " abc ", " def ", " ghi "); - assertTextArray("Multiple labels with comma and escape", - "ab\\\\,d\\\\\\,,g\\,i", "ab\\", "d\\,", "g,i"); - assertTextArray("Multiple labels with comma and escape surrounded by spaces", - " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\ ", " d\\, ", " g,i "); - } -} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java new file mode 100644 index 000000000..0e6caaf87 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java @@ -0,0 +1,243 @@ +/* + * 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.keyboard.internal; + +public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase { + // Chording input in alphabet. + public void testChordingAlphabet() { + // 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. + releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED); + + // 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 "ABC" key, switch back to alphabet. + releaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + } + + // Chording input in shift locked. + public void testChordingShiftLocked() { + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press shift key and hold, enter into choring shift state. + pressKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED); + // Press/release letter key. + chordingPressAndReleaseKey('Z', ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCK_SHIFTED); + // Release shift key, switch back to alphabet shift locked. + releaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCKED); + + // 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 locked. + releaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED); + } + + // Chording input in symbols. + public void testChordingSymbols() { + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Press "=\<" key and hold, enter into choring symbols shifted state. + pressKey(CODE_SHIFT, SYMBOLS_SHIFTED); + // Press/release symbol letter key. + chordingPressAndReleaseKey('1', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Release "=\<" key, switch back to symbols. + releaseKey(CODE_SHIFT, SYMBOLS_UNSHIFTED); + + // Press "ABC" key and hold, enter into choring alphabet state. + pressKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + // Press/release letter key. + chordingPressAndReleaseKey('a', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Release "ABC" key, switch back to symbols. + releaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED); + + // Alphabet shifted -> symbols -> "ABC" key + letter -> symbols + // -> alphabet. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press "ABC" key, enter into chording alphabet state. + pressKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + // Enter/release letter key. + chordingPressAndReleaseKey('a', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Release "ABC" key, switch back to symbols. + releaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shift locked -> symbols -> "ABC" key + letter -> symbols -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press "ABC" key, enter into chording alphabet shift locked. + pressKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED); + // Enter/release letter key. + chordingPressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Release "ABC" key, switch back to symbols. + releaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols -> "=\<" key + letter -> symbols -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press "=\<" key, enter into symbols shifted chording state. + pressKey(CODE_SHIFT, SYMBOLS_SHIFTED); + // Enter/release symbols shift letter key. + chordingPressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Release "=\<" key, switch back to symbols. + releaseKey(CODE_SHIFT, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + } + + // Chording input in symbol shifted. + public void testChordingSymbolsShifted() { + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + + // Press "?123" key and hold, enter into chording symbols state. + pressKey(CODE_SHIFT, SYMBOLS_UNSHIFTED); + // Press/release symbol letter key. + chordingPressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Release "=\<" key, switch back to symbols shifted state. + releaseKey(CODE_SHIFT, SYMBOLS_SHIFTED); + + // Press "ABC" key and hold, enter into choring alphabet state. + pressKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + // Press/release letter key. + chordingPressAndReleaseKey('a', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Release "ABC" key, switch back to symbols. + releaseKey(CODE_SYMBOL, SYMBOLS_SHIFTED); + + // Alphabet shifted -> symbols shifted -> "ABC" key + letter -> symbols shifted -> + // alphabet. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press "ABC" key, enter into chording alphabet state. + pressKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + // Enter/release letter key. + chordingPressAndReleaseKey('a', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Release "ABC" key, switch back to symbols shifted. + releaseKey(CODE_SYMBOL, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shift locked -> symbols shifted -> "ABC" key + letter -> symbols shifted + // -> alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press "ABC" key, enter into chording alphabet shift locked. + pressKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED); + // Enter/release letter key. + chordingPressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Release "ABC" key, switch back to symbols shifted. + releaseKey(CODE_SYMBOL, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols shifted -> "=\<" key + letter -> symbols shifted + // -> alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press "=\<" key, enter into symbols chording state. + pressKey(CODE_SHIFT, SYMBOLS_UNSHIFTED); + // Enter/release symbols letter key. + chordingPressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Release "=\<" key, switch back to symbols shifted. + releaseKey(CODE_SHIFT, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + } + + // Chording input in automatic upper case. + public void testChordingAutomaticUpperCase() { + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + + // Update shift state with auto caps enabled. + pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + // Press shift key and hold, enter into chording 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. + releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED); + + // Update shift state with auto caps enabled. + pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + // Press "123?" key and hold, enter into chording 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. + releaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED); + } + + // Chording letter key with shift key. + public void testChordingLetterAndShiftKey() { + // Press letter key and hold. + pressKey('z', ALPHABET_UNSHIFTED); + // Press shift key, {@link PointerTracker} will fire a phantom release letter key. + chordingReleaseKey('z', ALPHABET_UNSHIFTED); + chordingPressKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED); + // Press another letter key and hold. + chordingPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Release shift key + releaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java new file mode 100644 index 000000000..de2a50fcf --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java @@ -0,0 +1,755 @@ +/* + * 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.keyboard.internal; + +public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase { + // Shift key in alphabet. + public void testShiftAlphabet() { + // Press/release shift key, enter into alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Press/release shift key, enter into alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release letter key, switch back to alphabet. + pressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + } + + // Shift key in symbols. + public void testShiftSymbols() { + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + + // Press/release "?123" key, back to symbols. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release symbol letter key, remain in symbols shifted. + pressAndReleaseKey('1', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + } + + // Switching between alphabet and symbols. + public void testAlphabetAndSymbols() { + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, back to alphabet. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, back to alphabet. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Press/release "?123" key, back to symbols (not symbols shifted). + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + } + + // Switching between alphabet shifted and symbols. + public void testAlphabetShiftedAndSymbols() { + // Press/release shift key, enter into alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, back to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Press/release shift key, enter into alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\< key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, back to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + } + + // Switching between alphabet shift locked and symbols. + public void testAlphabetShiftLockedAndSymbols() { + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, back to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, back to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, back to symbols (not symbols shifted). + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + } + + // Automatic switch back to alphabet by space key. + public void testSwitchBackBySpace() { + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter symbol letter. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter space, switch back to alphabet. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter symbol shift letter. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter space, switch back to alphabet. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_SHIFTED, ALPHABET_UNSHIFTED); + // Press/release "?123" key, enter into symbols (not symbols shifted). + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + } + + // Automatic switch back to alphabet shift locked test by space key. + public void testSwitchBackBySpaceShiftLocked() { + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter symbol letter. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter space, switch back to alphabet shift locked. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_UNSHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter symbol shift letter. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter space, switch back to alphabet shift locked. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_SHIFTED, ALPHABET_SHIFT_LOCKED); + } + + // Automatic switch back to alphabet by registered letters. + public void testSwitchBackChar() { + // Set switch back chars. + final String switchBackSymbols = "'"; + final int switchBackCode = switchBackSymbols.codePointAt(0); + setLayoutSwitchBackSymbols(switchBackSymbols); + loadKeyboard(ALPHABET_UNSHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter symbol letter. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter switch back letter, switch back to alphabet. + pressAndReleaseKey(switchBackCode, SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter symbol shift letter. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter switch abck letter, switch back to alphabet. + pressAndReleaseKey(switchBackCode, SYMBOLS_SHIFTED, ALPHABET_UNSHIFTED); + } + + // Automatic switch back to alphabet shift locked by registered letters. + public void testSwitchBackCharShiftLocked() { + // Set switch back chars. + final String switchBackSymbols = "'"; + final int switchBackCode = switchBackSymbols.codePointAt(0); + setLayoutSwitchBackSymbols(switchBackSymbols); + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter symbol letter. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter switch back letter, switch back to alphabet shift locked. + pressAndReleaseKey(switchBackCode, SYMBOLS_UNSHIFTED, ALPHABET_SHIFT_LOCKED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter symbol shift letter. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter switch back letter, switch back to alphabet shift locked. + pressAndReleaseKey(switchBackCode, SYMBOLS_SHIFTED, ALPHABET_SHIFT_LOCKED); + } + + // Automatic upper case test + public void testAutomaticUpperCase() { + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + // Load keyboard, should be in automatic shifted. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release letter key, switch to alphabet. + pressAndReleaseKey('A', ALPHABET_AUTOMATIC_SHIFTED, ALPHABET_UNSHIFTED); + // Press/release auto caps trigger letter, should be in automatic shifted. + pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Press/release letter key, remain in alphabet. + pressAndReleaseKey('a', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Press/release auto caps trigger letter, should be in automatic shifted. + pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release symbol letter key, remain in symbols. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release space, switch back to automatic shifted. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release symbol shift letter key, remain in symbols shifted. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release space, switch back to automatic shifted. + pressAndReleaseKey(CODE_SPACE, SYMBOLS_SHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + } + + // Long press shift key. + public void testLongPressShift() { + // Set auto caps mode off. + setAutoCapsMode(NO_AUTO_CAPS); + // Load keyboard, should be in alphabet. + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release letter key, remain in shift locked. + pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Press/release word separator, remain in shift locked. + pressAndReleaseKey(CODE_SPACE, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Long press shift key, back to alphabet. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + // Load keyboard, should be in automatic shifted. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release shift key, back to alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + } + + // Double tap shift key. + public void testDoubleTapShift() { + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Press/release shift key, enter alphabet manual shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + // Load keyboard, should be in automatic shifted. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // First shift key tap. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + // Second shift key tap. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + } + + // Update shift state. + public void testUpdateShiftState() { + // Set auto caps mode off. + setAutoCapsMode(NO_AUTO_CAPS); + // Load keyboard, should be in alphabet. + loadKeyboard(ALPHABET_UNSHIFTED); + // Update shift state, remained in alphabet. + updateShiftState(ALPHABET_UNSHIFTED); + + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Update shift state, back to alphabet. + updateShiftState(ALPHABET_UNSHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Update shift state, remained in alphabet shift locked. + updateShiftState(ALPHABET_SHIFT_LOCKED); + // Long press shift key, back to alphabet. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Update shift state, remained in symbols. + updateShiftState(SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Update shift state, remained in symbols shifted. + updateShiftState(SYMBOLS_SHIFTED); + + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + // Load keyboard, should be in automatic shifted. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + // Update shift state, remained in automatic shifted. + updateShiftState(ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release shift key, enter alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Update shift state, enter to automatic shifted (not alphabet shifted). + updateShiftState(ALPHABET_AUTOMATIC_SHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Update shift state, remained in alphabet shift locked (not automatic shifted). + updateShiftState(ALPHABET_SHIFT_LOCKED); + // Long press shift key, back to alphabet. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + + // Load keyboard, should be in automatic shifted. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Update shift state, remained in symbols. + updateShiftState(SYMBOLS_UNSHIFTED); + + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Update shift state, remained in symbols shifted. + updateShiftState(SYMBOLS_SHIFTED); + } + + // Sliding input in alphabet. + public void testSlidingAlphabet() { + // Alphabet -> shift key + letter -> alphabet. + // Press and slide from shift key, enter alphabet shifted. + pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Enter/release letter key, switch back to alphabet. + pressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet -> "?123" key + letter -> alphabet. + // Press and slide from "123?" key, enter symbols. + pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter/release into symbol letter key, switch back to alphabet. + pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shifted -> shift key + letter -> alphabet. + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press and slide from shift key, remain alphabet shifted. + pressAndSlideFromKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Enter/release letter key, switch back to alphabet (not alphabet shifted). + pressAndReleaseKey('Z', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shifted -> "?123" key + letter -> alphabet. + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press and slide from "123?" key, enter symbols. + pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter/release into symbol letter key, switch back to alphabet (not alphabet shifted). + pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shift locked -> shift key + letter -> alphabet shift locked. + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press and slide from "123?" key, enter symbols. + pressAndSlideFromKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter/release into symbol letter key, switch back to alphabet shift locked. + pressAndReleaseKey('!', SYMBOLS_UNSHIFTED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> "?123" key + letter -> alphabet shift locked. + // Press and slide from shift key, enter alphabet shifted. + pressAndSlideFromKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Enter/release letter key, switch back to shift locked. + pressAndReleaseKey('Z', ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + } + + // Sliding input in symbols. + public void testSlidingSymbols() { + // Symbols -> "=\<" key + letter -> symbols. + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press and slide from shift key, enter symols shifted. + pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter/release symbol shifted letter key, switch back to symbols. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED); + + // Symbols -> "ABC" key + letter -> Symbols. + // Press and slide from "ABC" key, enter alphabet. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Enter/release letter key, switch back to symbols. + pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shifted -> symbols -> "ABC" key + letter -> symbols -> + // alphabet. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press and slide from "ABC" key. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Enter/release letter key, switch back to symbols. + pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shift locked -> symbols -> "ABC" key + letter -> symbols -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press and slide from "ABC" key, enter alphabet shift locked. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Enter/release letter key, switch back to symbols. + pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols -> "=\<" key + letter -> symbols -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press and slide from "=\<" key, enter symbols shifted. + pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Enter/release symbols shift letter key, switch back to symbols. + pressAndReleaseKey('~', SYMBOLS_SHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + } + + // Sliding input in symbols shifted. + public void testSlidingSymbolsShifted() { + // Symbols shifted -> "?123" + letter -> symbols shifted. + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press and slide from shift key, enter symbols. + pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter/release symbol letter key, switch back to symbols shifted. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED); + + // Symbols shifted -> "ABC" key + letter -> symbols shifted. + // Press and slide from "ABC" key, enter alphabet. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Enter/release letter key, switch back to symbols shifted. + pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shifted -> symbols shifted -> "ABC" + letter -> symbols shifted -> + // alphabet. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press and slide from "ABC" key. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Enter/release letter key, switch back to symbols shifted. + pressAndReleaseKey('a', ALPHABET_UNSHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet (not alphabet shifted). + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + + // Alphabet shift locked -> symbols shifted -> "ABC" + letter -> symbols shifted -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press and slide from "ABC" key. + pressAndSlideFromKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Enter/release letter key, switch back to symbols shifted. + pressAndReleaseKey('A', ALPHABET_SHIFT_LOCKED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols shifted -> "?123" + letter -> symbols shifted -> + // alphabet shift locked. + // Load keyboard + loadKeyboard(ALPHABET_UNSHIFTED); + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter into symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter into symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press and slide from "?123" key. + pressAndSlideFromKey(CODE_SHIFT, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Enter/release symbol letter key, switch back to symbols shifted. + pressAndReleaseKey('1', SYMBOLS_UNSHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, switch to alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + } + + // Change focus to new text field. + public void testChangeFocus() { + // Press/release shift key. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_UNSHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Change focus to new text field. + loadKeyboard(ALPHABET_UNSHIFTED); + + // Press/release "?123" key. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_UNSHIFTED); + + // Press/release "?123" key. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_UNSHIFTED); + } + + // Change focus to auto caps text field. + public void testChangeFocusAutoCaps() { + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + + // Update shift state. + updateShiftState(ALPHABET_AUTOMATIC_SHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release shift key, enter alphabet. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Change focus to new text field. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release "?123" key. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + + // Press/release "?123" key. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Change focus to new text field. + loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED); + } + + // Change orientation. + public void testChangeOrientation() { + // Alphabet -> rotate -> alphabet. + updateShiftState(ALPHABET_UNSHIFTED); + // Rotate device, remain in alphabet. + rotateDevice(ALPHABET_UNSHIFTED); + + // Alphabet shifted -> rotate -> alphabet shifted. + // Press/release shift key, enter alphabet shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rotate device, remain in alphabet shifted. + rotateDevice(ALPHABET_MANUAL_SHIFTED); + + // Alphabet shift locked -> rotate -> alphabet shift locked. + // Long press shift key, enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Rotate device, remain in alphabet shift locked. + rotateDevice(ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols -> rotate -> symbols -> + // Alphabet shift locked. + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Rotate device, remain in symbols, + rotateDevice(SYMBOLS_UNSHIFTED); + // Press/release "ABC" key, alphabet shift locked state should be maintained. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols shifted -> rotate -> symbols shifted -> + // Alphabet shift locked. + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Rotate device, remain in symbols shifted. + rotateDevice(SYMBOLS_SHIFTED); + // Press/release "ABC" key, alphabet shift locked state should be maintained. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + + // Alphabet shift locked -> symbols shifted -> alphabet shift locked -> rotate -> + // Alphabet shift locked -> symbols. + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, enter alphabet shift locked. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_SHIFT_LOCKED, ALPHABET_SHIFT_LOCKED); + // Rotate device, remain in alphabet shift locked. + rotateDevice(ALPHABET_SHIFT_LOCKED); + // Press/release "?123" key, enter symbols (not symbols shifted). + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + + // Alphabet -> symbols shifted -> alphabet -> rotate -> + // Alphabet -> symbols. + loadKeyboard(ALPHABET_UNSHIFTED); + // Press/release "?123" key, enter symbols. + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + // Press/release "=\<" key, enter symbols shifted. + pressAndReleaseKey(CODE_SHIFT, SYMBOLS_SHIFTED, SYMBOLS_SHIFTED); + // Press/release "ABC" key, enter alphabet. + pressAndReleaseKey(CODE_SYMBOL, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Rotate device, remain in alphabet shift locked. + rotateDevice(ALPHABET_UNSHIFTED); + // Press/release "?123" key, enter symbols (not symbols shifted). + pressAndReleaseKey(CODE_SYMBOL, SYMBOLS_UNSHIFTED, SYMBOLS_UNSHIFTED); + } + + // Rapidly type shift key. + public void testRapidShiftTyping() { + // Press/release shift key + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Press/release shift key to enter alphabet manual shifted. + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Press/release shift key + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('j', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Long press shift key to enter alphabet shift locked. + longPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_SHIFT_LOCKED); + // Press/release shift key + pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('j', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + + // Set auto caps mode on. + setAutoCapsMode(AUTO_CAPS); + // Press/release auto caps trigger letter to enter alphabet automatic shifted. + pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED); + // Press/release shift key + pressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('j', ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + // Rapidly press/release shift key. + secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_MANUAL_SHIFTED, ALPHABET_MANUAL_SHIFTED); + // Rapidly press/release letter key. + secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java new file mode 100644 index 000000000..96a54668c --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.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.keyboard.internal; + +import android.test.AndroidTestCase; + +public class KeyboardStateTestsBase extends AndroidTestCase + implements MockKeyboardSwitcher.Constants { + protected MockKeyboardSwitcher mSwitcher; + + private String mLayoutSwitchBackSymbols = ""; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mSwitcher = new MockKeyboardSwitcher(); + mSwitcher.setAutoCapsMode(NO_AUTO_CAPS); + + loadKeyboard(ALPHABET_UNSHIFTED); + } + + public void setAutoCapsMode(boolean autoCaps) { + mSwitcher.setAutoCapsMode(autoCaps); + } + + public void setLayoutSwitchBackSymbols(String switchBackSymbols) { + mLayoutSwitchBackSymbols = switchBackSymbols; + } + + private static void assertLayout(int expected, int actual) { + assertTrue("expected=" + MockKeyboardSwitcher.getLayoutName(expected) + + " actual=" + MockKeyboardSwitcher.getLayoutName(actual), + expected == actual); + } + + public void updateShiftState(int afterUpdate) { + mSwitcher.updateShiftState(); + assertLayout(afterUpdate, mSwitcher.getLayoutId()); + } + + public void loadKeyboard(int afterLoad) { + mSwitcher.loadKeyboard(mLayoutSwitchBackSymbols); + updateShiftState(afterLoad); + } + + public void rotateDevice(int afterRotate) { + mSwitcher.saveKeyboardState(); + mSwitcher.loadKeyboard(mLayoutSwitchBackSymbols); + assertLayout(afterRotate, mSwitcher.getLayoutId()); + } + + private void pressKeyWithoutTimerExpire(int code, int afterPress) { + mSwitcher.onPressKey(code); + assertLayout(afterPress, mSwitcher.getLayoutId()); + } + + public void pressKey(int code, int afterPress) { + mSwitcher.expireDoubleTapTimeout(); + pressKeyWithoutTimerExpire(code, afterPress); + } + + public void releaseKey(int code, int afterRelease) { + mSwitcher.onCodeInput(code, SINGLE); + mSwitcher.onReleaseKey(code, NOT_SLIDING); + assertLayout(afterRelease, mSwitcher.getLayoutId()); + } + + public void pressAndReleaseKey(int code, int afterPress, int afterRelease) { + pressKey(code, afterPress); + releaseKey(code, afterRelease); + } + + public void chordingPressKey(int code, int afterPress) { + pressKey(code, afterPress); + } + + public void chordingReleaseKey(int code, int afterRelease) { + mSwitcher.onCodeInput(code, MULTI); + mSwitcher.onReleaseKey(code, NOT_SLIDING); + assertLayout(afterRelease, mSwitcher.getLayoutId()); + } + + public void chordingPressAndReleaseKey(int code, int afterPress, int afterRelease) { + chordingPressKey(code, afterPress); + chordingReleaseKey(code, afterRelease); + } + + public void pressAndSlideFromKey(int code, int afterPress, int afterSlide) { + pressKey(code, afterPress); + mSwitcher.onReleaseKey(code, SLIDING); + assertLayout(afterSlide, mSwitcher.getLayoutId()); + } + + public void longPressAndReleaseKey(int code, int afterPress, int afterLongPress) { + pressKey(code, afterPress); + mSwitcher.onLongPressTimeout(code); + assertLayout(afterLongPress, mSwitcher.getLayoutId()); + releaseKey(code, afterLongPress); + } + + public void secondPressAndReleaseKey(int code, int afterPress, int afterRelease) { + pressKeyWithoutTimerExpire(code, 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 new file mode 100644 index 000000000..999e08a8d --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java @@ -0,0 +1,193 @@ +/* + * 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.keyboard.internal; + +import com.android.inputmethod.keyboard.Keyboard; + +public class MockKeyboardSwitcher implements KeyboardState.SwitchActions { + public interface Constants { + // Argument for {@link KeyboardState#onPressKey} and {@link KeyboardState#onReleaseKey}. + public static final boolean NOT_SLIDING = false; + public static final boolean SLIDING = true; + // Argument for {@link KeyboardState#onCodeInput}. + public static final boolean SINGLE = true; + public static final boolean MULTI = false; + public static final boolean NO_AUTO_CAPS = false; + public static final boolean AUTO_CAPS = true; + + public static final int CODE_SHIFT = Keyboard.CODE_SHIFT; + public static final int CODE_SYMBOL = Keyboard.CODE_SWITCH_ALPHA_SYMBOL; + public static final int CODE_SPACE = Keyboard.CODE_SPACE; + public static final int CODE_AUTO_CAPS_TRIGGER = Keyboard.CODE_SPACE; + + public static final int ALPHABET_UNSHIFTED = 0; + public static final int ALPHABET_MANUAL_SHIFTED = 1; + public static final int ALPHABET_AUTOMATIC_SHIFTED = 2; + public static final int ALPHABET_SHIFT_LOCKED = 3; + public static final int ALPHABET_SHIFT_LOCK_SHIFTED = 4; + public static final int SYMBOLS_UNSHIFTED = 5; + public static final int SYMBOLS_SHIFTED = 6; + } + + private int mLayout = Constants.ALPHABET_UNSHIFTED; + + private boolean mAutoCapsMode = Constants.NO_AUTO_CAPS; + // Following InputConnection's behavior. Simulating InputType.TYPE_TEXT_FLAG_CAP_WORDS. + private boolean mAutoCapsState = true; + + private boolean mIsInDoubleTapTimeout; + private int mLongPressTimeoutCode; + + private final KeyboardState mState = new KeyboardState(this); + + public int getLayoutId() { + return mLayout; + } + + public static String getLayoutName(int layoutId) { + switch (layoutId) { + case Constants.ALPHABET_UNSHIFTED: return "ALPHABET_UNSHIFTED"; + case Constants.ALPHABET_MANUAL_SHIFTED: return "ALPHABET_MANUAL_SHIFTED"; + case Constants.ALPHABET_AUTOMATIC_SHIFTED: return "ALPHABET_AUTOMATIC_SHIFTED"; + case Constants.ALPHABET_SHIFT_LOCKED: return "ALPHABET_SHIFT_LOCKED"; + case Constants.ALPHABET_SHIFT_LOCK_SHIFTED: return "ALPHABET_SHIFT_LOCK_SHIFTED"; + case Constants.SYMBOLS_UNSHIFTED: return "SYMBOLS_UNSHIFTED"; + case Constants.SYMBOLS_SHIFTED: return "SYMBOLS_SHIFTED"; + default: return "UNKNOWN<" + layoutId + ">"; + } + } + + public void setAutoCapsMode(boolean autoCaps) { + mAutoCapsMode = autoCaps; + } + + public void expireDoubleTapTimeout() { + mIsInDoubleTapTimeout = false; + } + + @Override + public void setAlphabetKeyboard() { + mLayout = Constants.ALPHABET_UNSHIFTED; + } + + @Override + public void setAlphabetManualShiftedKeyboard() { + mLayout = Constants.ALPHABET_MANUAL_SHIFTED; + } + + @Override + public void setAlphabetAutomaticShiftedKeyboard() { + mLayout = Constants.ALPHABET_AUTOMATIC_SHIFTED; + } + + @Override + public void setAlphabetShiftLockedKeyboard() { + mLayout = Constants.ALPHABET_SHIFT_LOCKED; + } + + @Override + public void setAlphabetShiftLockShiftedKeyboard() { + mLayout = Constants.ALPHABET_SHIFT_LOCK_SHIFTED; + } + + @Override + public void setSymbolsKeyboard() { + mLayout = Constants.SYMBOLS_UNSHIFTED; + } + + @Override + public void setSymbolsShiftedKeyboard() { + mLayout = Constants.SYMBOLS_SHIFTED; + } + + @Override + public void requestUpdatingShiftState() { + mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState); + } + + @Override + public void startDoubleTapTimer() { + mIsInDoubleTapTimeout = true; + } + + @Override + public void cancelDoubleTapTimer() { + mIsInDoubleTapTimeout = false; + } + + @Override + public boolean isInDoubleTapTimeout() { + return mIsInDoubleTapTimeout; + } + + @Override + public void startLongPressTimer(int code) { + mLongPressTimeoutCode = code; + } + + @Override + public void cancelLongPressTimer() { + mLongPressTimeoutCode = 0; + } + + @Override + public void hapticAndAudioFeedback(int code) { + // Nothing to do. + } + + public void onLongPressTimeout(int code) { + // TODO: Handle simultaneous long presses. + if (mLongPressTimeoutCode == code) { + mLongPressTimeoutCode = 0; + mState.onLongPressTimeout(code); + } + } + + public void updateShiftState() { + mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState); + } + + public void loadKeyboard(String layoutSwitchBackSymbols) { + mState.onLoadKeyboard(layoutSwitchBackSymbols); + } + + public void saveKeyboardState() { + mState.onSaveKeyboardState(); + } + + public void onPressKey(int code) { + mState.onPressKey(code); + } + + public void onReleaseKey(int code, boolean withSliding) { + mState.onReleaseKey(code, withSliding); + if (mLongPressTimeoutCode == code) { + mLongPressTimeoutCode = 0; + } + } + + public void onCodeInput(int code, boolean isSinglePointer) { + if (Keyboard.isLetterCode(code)) { + mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER); + } + mState.onCodeInput(code, isSinglePointer, mAutoCapsMode && mAutoCapsState); + } + + public void onCancelInput(boolean isSinglePointer) { + mState.onCancelInput(isSinglePointer); + } +}
\ No newline at end of file diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java deleted file mode 100644 index 798fca0f5..000000000 --- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.content.res.Resources; -import android.test.AndroidTestCase; - -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.R; - -public class MoreKeySpecParserTests extends AndroidTestCase { - private Resources mRes; - - private static final int ICON_SETTINGS_KEY = 5; - private static final int ICON_UNDEFINED = KeyboardIconsSet.ICON_UNDEFINED; - - private static final String CODE_SETTINGS = "@integer/key_settings"; - private static final String ICON_SETTINGS = "@icon/" + ICON_SETTINGS_KEY; - private static final String CODE_NON_EXISTING = "@integer/non_existing"; - private static final String ICON_NON_EXISTING = "@icon/non_existing"; - - private int mCodeSettings; - - @Override - protected void setUp() { - Resources res = getContext().getResources(); - mRes = res; - - final String packageName = res.getResourcePackageName(R.string.english_ime_name); - final int codeId = res.getIdentifier(CODE_SETTINGS.substring(1), null, packageName); - mCodeSettings = res.getInteger(codeId); - } - - private void assertParser(String message, String moreKeySpec, String expectedLabel, - String expectedOutputText, int expectedIcon, int expectedCode) { - String actualLabel = MoreKeySpecParser.getLabel(moreKeySpec); - assertEquals(message + ": label:", expectedLabel, actualLabel); - - String actualOutputText = MoreKeySpecParser.getOutputText(moreKeySpec); - assertEquals(message + ": ouptputText:", expectedOutputText, actualOutputText); - - int actualIcon = MoreKeySpecParser.getIconId(moreKeySpec); - assertEquals(message + ": icon:", expectedIcon, actualIcon); - - int actualCode = MoreKeySpecParser.getCode(mRes, moreKeySpec); - assertEquals(message + ": codes value:", expectedCode, actualCode); - } - - private void assertParserError(String message, String moreKeySpec, String expectedLabel, - String expectedOutputText, int expectedIcon, int expectedCode) { - try { - assertParser(message, moreKeySpec, expectedLabel, expectedOutputText, expectedIcon, - expectedCode); - fail(message); - } catch (MoreKeySpecParser.MoreKeySpecParserError pcpe) { - // success. - } - } - - public void testSingleLetter() { - assertParser("Single letter", "a", - "a", null, ICON_UNDEFINED, 'a'); - assertParser("Single escaped bar", "\\|", - "|", null, ICON_UNDEFINED, '|'); - assertParser("Single escaped escape", "\\\\", - "\\", null, ICON_UNDEFINED, '\\'); - assertParser("Single comma", ",", - ",", null, ICON_UNDEFINED, ','); - assertParser("Single escaped comma", "\\,", - ",", null, ICON_UNDEFINED, ','); - assertParser("Single escaped letter", "\\a", - "a", null, ICON_UNDEFINED, 'a'); - assertParser("Single at", "@", - "@", null, ICON_UNDEFINED, '@'); - assertParser("Single escaped at", "\\@", - "@", null, ICON_UNDEFINED, '@'); - assertParser("Single letter with outputText", "a|abc", - "a", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with escaped outputText", "a|a\\|c", - "a", "a|c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with comma outputText", "a|a,b", - "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with escaped comma outputText", "a|a\\,b", - "a", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with outputText starts with at", "a|@bc", - "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with outputText contains at", "a|a@c", - "a", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with escaped at outputText", "a|\\@bc", - "a", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single escaped escape with outputText", "\\\\|\\\\", - "\\", "\\", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single escaped bar with outputText", "\\||\\|", - "|", "|", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Single letter with code", "a|" + CODE_SETTINGS, - "a", null, ICON_UNDEFINED, mCodeSettings); - } - - public void testLabel() { - assertParser("Simple label", "abc", - "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped bar", "a\\|c", - "a|c", "a|c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped escape", "a\\\\c", - "a\\c", "a\\c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with comma", "a,c", - "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped comma", "a\\,c", - "a,c", "a,c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label starts with at", "@bc", - "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label contains at", "a@c", - "a@c", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped at", "\\@bc", - "@bc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped letter", "\\abc", - "abc", "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with outputText", "abc|def", - "abc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with comma and outputText", "a,c|def", - "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Escaped comma label with outputText", "a\\,c|def", - "a,c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Escaped label with outputText", "a\\|c|def", - "a|c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Escaped escape label with outputText", "a\\\\|def", - "a\\", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label starts with at and outputText", "@bc|def", - "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label contains at label and outputText", "a@c|def", - "a@c", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Escaped at label with outputText", "\\@bc|def", - "@bc", "def", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with comma outputText", "abc|a,b", - "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped comma outputText", "abc|a\\,b", - "abc", "a,b", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with outputText starts with at", "abc|@bc", - "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with outputText contains at", "abc|a@c", - "abc", "a@c", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped at outputText", "abc|\\@bc", - "abc", "@bc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Escaped bar label with escaped bar outputText", "a\\|c|d\\|f", - "a|c", "d|f", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParser("Label with code", "abc|" + CODE_SETTINGS, - "abc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS, - "a|c", null, ICON_UNDEFINED, mCodeSettings); - } - - public void testIconAndCode() { - assertParser("Icon with outputText", ICON_SETTINGS + "|abc", - null, "abc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); - assertParser("Icon with outputText starts with at", ICON_SETTINGS + "|@bc", - null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); - assertParser("Icon with outputText contains at", ICON_SETTINGS + "|a@c", - null, "a@c", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); - assertParser("Icon with escaped at outputText", ICON_SETTINGS + "|\\@bc", - null, "@bc", ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); - assertParser("Label starts with at and code", "@bc|" + CODE_SETTINGS, - "@bc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Label contains at and code", "a@c|" + CODE_SETTINGS, - "a@c", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Escaped at label with code", "\\@bc|" + CODE_SETTINGS, - "@bc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS, - null, null, ICON_SETTINGS_KEY, mCodeSettings); - } - - public void testFormatError() { - assertParserError("Empty spec", "", null, - null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Empty label with outputText", "|a", - null, "a", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParserError("Empty label with code", "|" + CODE_SETTINGS, - null, null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Empty outputText with label", "a|", - "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Empty outputText with icon", ICON_SETTINGS + "|", - null, null, ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); - assertParserError("Empty icon and code", "|", - null, null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Icon without code", ICON_SETTINGS, - null, null, ICON_SETTINGS_KEY, Keyboard.CODE_DUMMY); - assertParser("Non existing icon", ICON_NON_EXISTING + "|abc", - null, "abc", ICON_UNDEFINED, Keyboard.CODE_DUMMY); - assertParserError("Non existing code", "abc|" + CODE_NON_EXISTING, - "abc", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Third bar at end", "a|b|", - "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Multiple bar", "a|b|c", - "a", null, ICON_UNDEFINED, Keyboard.CODE_UNSPECIFIED); - assertParserError("Multiple bar with label and code", "a|" + CODE_SETTINGS + "|c", - "a", null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Multiple bar with icon and outputText", ICON_SETTINGS + "|b|c", - null, null, ICON_SETTINGS_KEY, Keyboard.CODE_UNSPECIFIED); - assertParserError("Multiple bar with icon and code", - ICON_SETTINGS + "|" + CODE_SETTINGS + "|c", - null, null, ICON_SETTINGS_KEY, mCodeSettings); - } -} diff --git a/tests/src/com/android/inputmethod/latin/ArbitrarySubtype.java b/tests/src/com/android/inputmethod/latin/ArbitrarySubtype.java new file mode 100644 index 000000000..1e3482ca7 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/ArbitrarySubtype.java @@ -0,0 +1,54 @@ +/* + * 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 com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; + +public class ArbitrarySubtype extends InputMethodSubtypeCompatWrapper { + final String mLocale; + final String mExtraValue; + + public ArbitrarySubtype(final String locale, final String extraValue) { + super(locale); + mLocale = locale; + mExtraValue = extraValue; + } + + public String getLocale() { + return mLocale; + } + + public String getExtraValue() { + return mExtraValue; + } + + public String getMode() { + return "keyboard"; + } + + public String getExtraValueOf(final String key) { + if (LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE.equals(key)) { + return ""; + } else { + return null; + } + } + + public boolean containsExtraValueKey(final String key) { + return LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE.equals(key); + } +} diff --git a/tests/src/com/android/inputmethod/latin/EditDistanceTests.java b/tests/src/com/android/inputmethod/latin/EditDistanceTests.java index 75bd04938..c053a49e5 100644 --- a/tests/src/com/android/inputmethod/latin/EditDistanceTests.java +++ b/tests/src/com/android/inputmethod/latin/EditDistanceTests.java @@ -37,7 +37,7 @@ public class EditDistanceTests extends AndroidTestCase { * sitting */ public void testExample1() { - final int dist = Utils.editDistance("kitten", "sitting"); + final int dist = BinaryDictionary.editDistance("kitten", "sitting"); assertEquals("edit distance between 'kitten' and 'sitting' is 3", 3, dist); } @@ -50,26 +50,26 @@ public class EditDistanceTests extends AndroidTestCase { * S--unday */ public void testExample2() { - final int dist = Utils.editDistance("Saturday", "Sunday"); + final int dist = BinaryDictionary.editDistance("Saturday", "Sunday"); assertEquals("edit distance between 'Saturday' and 'Sunday' is 3", 3, dist); } public void testBothEmpty() { - final int dist = Utils.editDistance("", ""); + final int dist = BinaryDictionary.editDistance("", ""); assertEquals("when both string are empty, no edits are needed", 0, dist); } public void testFirstArgIsEmpty() { - final int dist = Utils.editDistance("", "aaaa"); + final int dist = BinaryDictionary.editDistance("", "aaaa"); assertEquals("when only one string of the arguments is empty," + " the edit distance is the length of the other.", 4, dist); } public void testSecoondArgIsEmpty() { - final int dist = Utils.editDistance("aaaa", ""); + final int dist = BinaryDictionary.editDistance("aaaa", ""); assertEquals("when only one string of the arguments is empty," + " the edit distance is the length of the other.", 4, dist); @@ -78,27 +78,27 @@ public class EditDistanceTests extends AndroidTestCase { public void testSameStrings() { final String arg1 = "The quick brown fox jumps over the lazy dog."; final String arg2 = "The quick brown fox jumps over the lazy dog."; - final int dist = Utils.editDistance(arg1, arg2); + final int dist = BinaryDictionary.editDistance(arg1, arg2); assertEquals("when same strings are passed, distance equals 0.", 0, dist); } public void testSameReference() { final String arg = "The quick brown fox jumps over the lazy dog."; - final int dist = Utils.editDistance(arg, arg); + final int dist = BinaryDictionary.editDistance(arg, arg); assertEquals("when same string references are passed, the distance equals 0.", 0, dist); } public void testNullArg() { try { - Utils.editDistance(null, "aaa"); + BinaryDictionary.editDistance(null, "aaa"); fail("IllegalArgumentException should be thrown."); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { - Utils.editDistance("aaa", null); + BinaryDictionary.editDistance("aaa", null); fail("IllegalArgumentException should be thrown."); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java new file mode 100644 index 000000000..595fe5b10 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -0,0 +1,684 @@ +/* + * 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 android.content.Intent; +import android.content.SharedPreferences; +import android.os.Looper; +import android.os.MessageQueue; +import android.preference.PreferenceManager; +import android.test.ServiceTestCase; +import android.text.InputType; +import android.text.SpannableStringBuilder; +import android.text.style.SuggestionSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.view.View; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; // for proximity info +import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; + +import java.util.Arrays; +import java.util.HashMap; + +public class InputLogicTests extends ServiceTestCase<LatinIME> { + + private static final String PREF_DEBUG_MODE = "debug_mode"; + + private LatinIME mLatinIME; + private TextView mTextView; + private InputConnection mInputConnection; + + public InputLogicTests() { + super(LatinIME.class); + } + + // returns the previous setting value + private boolean setDebugMode(final boolean mode) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME); + final boolean previousDebugSetting = prefs.getBoolean(PREF_DEBUG_MODE, false); + final SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(PREF_DEBUG_MODE, true); + editor.commit(); + return previousDebugSetting; + } + + @Override + protected void setUp() { + try { + super.setUp(); + } catch (Exception e) { + e.printStackTrace(); + } + mTextView = new TextView(getContext()); + mTextView.setInputType(InputType.TYPE_CLASS_TEXT); + mTextView.setEnabled(true); + setupService(); + mLatinIME = getService(); + final boolean previousDebugSetting = setDebugMode(true); + mLatinIME.onCreate(); + setDebugMode(previousDebugSetting); + final EditorInfo ei = new EditorInfo(); + ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; + final InputConnection ic = mTextView.onCreateInputConnection(ei); + ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; + final LayoutInflater inflater = + (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + final ViewGroup vg = new FrameLayout(getContext()); + final View inputView = inflater.inflate(R.layout.input_view, vg); + mLatinIME.setInputView(inputView); + mLatinIME.onBindInput(); + mLatinIME.onCreateInputView(); + mLatinIME.onStartInputView(ei, false); + mLatinIME.onCreateInputMethodInterface().startInput(ic, ei); + mInputConnection = ic; + changeLanguage("en_US"); + } + + // We need to run the messages added to the handler from LatinIME. The only way to do + // that is to call Looper#loop() on the right looper, so we're going to get the looper + // object and call #loop() here. The messages in the handler actually run on the UI + // thread of the keyboard by design of the handler, so we want to call it synchronously + // on the same thread that the tests are running on to mimic the actual environment as + // closely as possible. + // Now, Looper#loop() never exits in normal operation unless the Looper#quit() method + // is called, so we need to do that at the right time so that #loop() returns at some + // point and we don't end up in an infinite loop. + // After we quit, the looper is still technically ready to process more messages but + // the handler will refuse to enqueue any because #quit() has been called and it + // explicitly tests for it on message enqueuing, so we'll have to reset it so that + // it lets us continue normal operation. + private void runMessages() { + // Here begins deep magic. + final Looper looper = mLatinIME.mHandler.getLooper(); + mLatinIME.mHandler.post(new Runnable() { + @Override + public void run() { + looper.quit(); + } + }); + // The only way to get out of Looper#loop() is to call #quit() on it (or on its queue). + // Once #quit() is called remaining messages are not processed, which is why we post + // a message that calls it instead of calling it directly. + looper.loop(); + + // Once #quit() has been called, the message queue has an "mQuiting" field that prevents + // any subsequent post in this queue. However the queue itself is still fully functional! + // If we have a way of resetting "queue.mQuiting" then we can continue using it as normal, + // coming back to this method to run the messages. + MessageQueue queue = looper.getQueue(); + try { + // However there is no way of doing it externally, and mQuiting is private. + // So... get out the big guns. + java.lang.reflect.Field f = MessageQueue.class.getDeclaredField("mQuiting"); + f.setAccessible(true); // What do you mean "private"? + f.setBoolean(queue, false); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + // type(int) and type(String): helper methods to send a code point resp. a string to LatinIME. + private void type(final int codePoint) { + // onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the + // code (although multitouch/slide input and other factors make the sequencing complicated). + // They are supposed to be entirely deconnected from the input logic from LatinIME point of + // view and only delegates to the parts of the code that care. So we don't include them here + // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies, + // but keep them in mind if something breaks. Commenting them out as is should work. + //mLatinIME.onPressKey(codePoint); + mLatinIME.onCodeInput(codePoint, + KeyboardActionListener.SPELL_CHECKER_COORDINATE, + KeyboardActionListener.SPELL_CHECKER_COORDINATE); + //mLatinIME.onReleaseKey(codePoint, false); + } + + private void type(final String stringToType) { + for (int i = 0; i < stringToType.length(); i = stringToType.offsetByCodePoints(i, 1)) { + type(stringToType.codePointAt(i)); + } + } + + private void waitForDictionaryToBeLoaded() { + int remainingAttempts = 10; + while (remainingAttempts > 0 && !mLatinIME.mSuggest.hasMainDictionary()) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + // Don't do much + } finally { + --remainingAttempts; + } + } + if (!mLatinIME.mSuggest.hasMainDictionary()) { + throw new RuntimeException("Can't initialize the main dictionary"); + } + } + + private void changeLanguage(final String locale) { + SubtypeSwitcher.getInstance().updateSubtype( + new ArbitrarySubtype(locale, LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE)); + waitForDictionaryToBeLoaded(); + } + + + // Helper to avoid writing the try{}catch block each time + private static void sleep(final int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) {} + } + + public void testTypeWord() { + final String WORD_TO_TYPE = "abcd"; + type(WORD_TO_TYPE); + assertEquals("type word", WORD_TO_TYPE, mTextView.getText().toString()); + } + + public void testPickSuggestionThenBackspace() { + final String WORD_TO_TYPE = "this"; + final String EXPECTED_RESULT = "this"; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); + type(Keyboard.CODE_DELETE); + assertEquals("press suggestion then backspace", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testPickAutoCorrectionThenBackspace() { + final String WORD_TO_TYPE = "tgis"; + final String WORD_TO_PICK = "this"; + final String EXPECTED_RESULT = "tgis"; + type(WORD_TO_TYPE); + // Choose the auto-correction, which is always in position 0. For "tgis", the + // auto-correction should be "this". + mLatinIME.pickSuggestionManually(0, WORD_TO_PICK); + mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); + assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK, + mTextView.getText().toString()); + type(Keyboard.CODE_DELETE); + assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testPickTypedWordOverAutoCorrectionThenBackspace() { + final String WORD_TO_TYPE = "tgis"; + final String EXPECTED_RESULT = "tgis"; + type(WORD_TO_TYPE); + // Choose the typed word, which should be in position 1 (because position 0 should + // be occupied by the "this" auto-correction, as checked by testAutoCorrect()) + mLatinIME.pickSuggestionManually(1, WORD_TO_TYPE); + mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); + assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE, + mTextView.getText().toString()); + type(Keyboard.CODE_DELETE); + assertEquals("pick typed word over auto-correction then backspace", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testPickDifferentSuggestionThenBackspace() { + final String WORD_TO_TYPE = "tgis"; + final String WORD_TO_PICK = "thus"; + final String EXPECTED_RESULT = "tgis"; + type(WORD_TO_TYPE); + // Choose the second suggestion, which should be in position 2 and should be "thus" + // when "tgis is typed. + mLatinIME.pickSuggestionManually(2, WORD_TO_PICK); + mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1); + assertEquals("pick different suggestion then backspace", WORD_TO_PICK, + mTextView.getText().toString()); + type(Keyboard.CODE_DELETE); + assertEquals("pick different suggestion then backspace", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testDeleteSelection() { + final String STRING_TO_TYPE = "some text delete me some text"; + final int SELECTION_START = 10; + final int SELECTION_END = 19; + final String EXPECTED_RESULT = "some text some text"; + type(STRING_TO_TYPE); + // There is no IMF to call onUpdateSelection for us so we must do it by hand. + // Send once to simulate the cursor actually responding to the move caused by typing. + // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor + // move with a move triggered by LatinIME inputting stuff. + mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); + mInputConnection.setSelection(SELECTION_START, SELECTION_END); + // And now we simulate the user actually selecting some text. + mLatinIME.onUpdateSelection(0, 0, SELECTION_START, SELECTION_END, -1, -1); + type(Keyboard.CODE_DELETE); + assertEquals("delete selection", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrect() { + final String STRING_TO_TYPE = "tgis "; + final String EXPECTED_RESULT = "this "; + type(STRING_TO_TYPE); + assertEquals("simple auto-correct", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrectForFrench() { + final String STRING_TO_TYPE = "irq "; + final String EXPECTED_RESULT = "ira "; + changeLanguage("fr"); + type(STRING_TO_TYPE); + assertEquals("simple auto-correct for French", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testAutoCorrectWithPeriod() { + final String STRING_TO_TYPE = "tgis."; + final String EXPECTED_RESULT = "this."; + type(STRING_TO_TYPE); + assertEquals("auto-correct with period", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrectWithPeriodThenRevert() { + final String STRING_TO_TYPE = "tgis."; + final String EXPECTED_RESULT = "tgis."; + type(STRING_TO_TYPE); + mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); + type(Keyboard.CODE_DELETE); + assertEquals("auto-correct with period then revert", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testDoubleSpace() { + final String STRING_TO_TYPE = "this "; + final String EXPECTED_RESULT = "this. "; + type(STRING_TO_TYPE); + assertEquals("double space make a period", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testCancelDoubleSpace() { + final String STRING_TO_TYPE = "this "; + final String EXPECTED_RESULT = "this "; + type(STRING_TO_TYPE); + type(Keyboard.CODE_DELETE); + assertEquals("double space make a period", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testBackspaceAtStartAfterAutocorrect() { + final String STRING_TO_TYPE = "tgis "; + final String EXPECTED_RESULT = "this "; + final int NEW_CURSOR_POSITION = 0; + type(STRING_TO_TYPE); + mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); + mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); + mLatinIME.onUpdateSelection(0, 0, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); + type(Keyboard.CODE_DELETE); + assertEquals("auto correct then move cursor to start of line then backspace", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrectThenMoveCursorThenBackspace() { + final String STRING_TO_TYPE = "and tgis "; + final String EXPECTED_RESULT = "andthis "; + final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t'); + type(STRING_TO_TYPE); + mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); + mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); + mLatinIME.onUpdateSelection(0, 0, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); + type(Keyboard.CODE_DELETE); + assertEquals("auto correct then move cursor then backspace", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testNoSpaceAfterManualPick() { + final String WORD_TO_TYPE = "this"; + final String EXPECTED_RESULT = WORD_TO_TYPE; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + assertEquals("no space after manual pick", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenType() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_TYPE = "is"; + final String EXPECTED_RESULT = "this is"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + type(WORD2_TO_TYPE); + assertEquals("manual pick then type", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testManualPickThenSeparator() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_TYPE = "!"; + final String EXPECTED_RESULT = "this!"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + type(WORD2_TO_TYPE); + assertEquals("manual pick then separator", EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testWordThenSpaceThenPunctuationFromStripTwice() { + final String WORD_TO_TYPE = "this "; + final String PUNCTUATION_FROM_STRIP = "!"; + final String EXPECTED_RESULT = "this!! "; + type(WORD_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + assertTrue("type word then type space should display punctuation strip", + mLatinIME.isShowingPunctuationList()); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + assertEquals("type word then type space then punctuation from strip twice", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenSeparatorForFrench() { + final String WORD1_TO_TYPE = "test"; + final String WORD2_TO_TYPE = "!"; + final String EXPECTED_RESULT = "test !"; + changeLanguage("fr"); + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + type(WORD2_TO_TYPE); + assertEquals("manual pick then separator for French", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testWordThenSpaceThenPunctuationFromStripTwiceForFrench() { + final String WORD_TO_TYPE = "test "; + final String PUNCTUATION_FROM_STRIP = "!"; + final String EXPECTED_RESULT = "test !!"; + changeLanguage("fr"); + type(WORD_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + assertTrue("type word then type space should display punctuation strip", + mLatinIME.isShowingPunctuationList()); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + assertEquals("type word then type space then punctuation from strip twice for French", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testWordThenSpaceThenPunctuationFromKeyboardTwice() { + final String WORD_TO_TYPE = "this !!"; + final String EXPECTED_RESULT = "this !!"; + type(WORD_TO_TYPE); + assertEquals("manual pick then space then punctuation from keyboard twice", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenPunctuationFromStripTwiceThenType() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_TYPE = "is"; + final String PUNCTUATION_FROM_STRIP = "!"; + final String EXPECTED_RESULT = "this!! is"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + mLatinIME.pickSuggestionManually(0, PUNCTUATION_FROM_STRIP); + type(WORD2_TO_TYPE); + assertEquals("pick word then pick punctuation twice then type", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenSpaceThenType() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_TYPE = " is"; + final String EXPECTED_RESULT = "this is"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + type(WORD2_TO_TYPE); + assertEquals("manual pick then space then type", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenManualPick() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_PICK = "is"; + final String EXPECTED_RESULT = "this is"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + // Here we fake picking a word through bigram prediction. This test is taking + // advantage of the fact that Latin IME blindly trusts the caller of #pickSuggestionManually + // to actually pass the right string. + mLatinIME.pickSuggestionManually(1, WORD2_TO_PICK); + assertEquals("manual pick then manual pick", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testManualPickThenManualPickWithPunctAtStart() { + final String WORD1_TO_TYPE = "this"; + final String WORD2_TO_PICK = "!is"; + final String EXPECTED_RESULT = "this!is"; + type(WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD1_TO_TYPE); + mLatinIME.pickSuggestionManually(1, WORD2_TO_PICK); + assertEquals("manual pick then manual pick a word with punct at start", EXPECTED_RESULT, + mTextView.getText().toString()); + } + + public void testDeleteWholeComposingWord() { + final String WORD_TO_TYPE = "this"; + type(WORD_TO_TYPE); + for (int i = 0; i < WORD_TO_TYPE.length(); ++i) { + type(Keyboard.CODE_DELETE); + } + assertEquals("delete whole composing word", "", mTextView.getText().toString()); + } + + public void testManuallyPickedWordThenColon() { + final String WORD_TO_TYPE = "this"; + final String PUNCTUATION = ":"; + final String EXPECTED_RESULT = "this:"; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + type(PUNCTUATION); + assertEquals("manually pick word then colon", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testManuallyPickedWordThenOpenParen() { + final String WORD_TO_TYPE = "this"; + final String PUNCTUATION = "("; + final String EXPECTED_RESULT = "this ("; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + type(PUNCTUATION); + assertEquals("manually pick word then open paren", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testManuallyPickedWordThenCloseParen() { + final String WORD_TO_TYPE = "this"; + final String PUNCTUATION = ")"; + final String EXPECTED_RESULT = "this)"; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + type(PUNCTUATION); + assertEquals("manually pick word then close paren", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testManuallyPickedWordThenSmiley() { + final String WORD_TO_TYPE = "this"; + final String SPECIAL_KEY = ":-)"; + final String EXPECTED_RESULT = "this :-)"; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + mLatinIME.onTextInput(SPECIAL_KEY); + assertEquals("manually pick word then press the smiley key", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testManuallyPickedWordThenDotCom() { + final String WORD_TO_TYPE = "this"; + final String SPECIAL_KEY = ".com"; + final String EXPECTED_RESULT = "this.com"; + type(WORD_TO_TYPE); + mLatinIME.pickSuggestionManually(0, WORD_TO_TYPE); + mLatinIME.onTextInput(SPECIAL_KEY); + assertEquals("manually pick word then press the .com key", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testTypeWordTypeDotThenPressDotCom() { + final String WORD_TO_TYPE = "this."; + final String SPECIAL_KEY = ".com"; + final String EXPECTED_RESULT = "this.com"; + type(WORD_TO_TYPE); + mLatinIME.onTextInput(SPECIAL_KEY); + assertEquals("type word type dot then press the .com key", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrectionWithSingleQuoteInside() { + final String WORD_TO_TYPE = "you'f "; + final String EXPECTED_RESULT = "you'd "; + type(WORD_TO_TYPE); + assertEquals("auto-correction with single quote inside", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + public void testAutoCorrectionWithSingleQuotesAround() { + final String WORD_TO_TYPE = "'tgis' "; + final String EXPECTED_RESULT = "'this' "; + type(WORD_TO_TYPE); + assertEquals("auto-correction with single quotes around", + EXPECTED_RESULT, mTextView.getText().toString()); + } + + // A helper class to ease span tests + private static class Span { + final SpannableStringBuilder mInputText; + final SuggestionSpan mSpan; + final int mStart; + final int mEnd; + // The supplied CharSequence should be an instance of SpannableStringBuilder, + // and it should contain exactly zero or one SuggestionSpan. Otherwise, an exception + // is thrown. + public Span(final CharSequence inputText) { + mInputText = (SpannableStringBuilder)inputText; + final SuggestionSpan[] spans = + mInputText.getSpans(0, mInputText.length(), SuggestionSpan.class); + if (0 == spans.length) { + mSpan = null; + mStart = -1; + mEnd = -1; + } else if (1 == spans.length) { + mSpan = spans[0]; + mStart = mInputText.getSpanStart(mSpan); + mEnd = mInputText.getSpanEnd(mSpan); + } else { + throw new RuntimeException("Expected one SuggestionSpan, found " + spans.length); + } + } + public boolean isAutoCorrectionIndicator() { + return 0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & mSpan.getFlags()); + } + } + + static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200; // The message is posted with a 100 ms delay + public void testBlueUnderline() { + final String STRING_TO_TYPE = "tgis"; + final int EXPECTED_SPAN_START = 0; + final int EXPECTED_SPAN_END = 4; + type(STRING_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + final Span span = new Span(mTextView.getText()); + assertEquals("show blue underline, span start", EXPECTED_SPAN_START, span.mStart); + assertEquals("show blue underline, span end", EXPECTED_SPAN_END, span.mEnd); + assertEquals("show blue underline, span color", true, span.isAutoCorrectionIndicator()); + } + + public void testBlueUnderlineDisappears() { + final String STRING_1_TO_TYPE = "tgis"; + final String STRING_2_TO_TYPE = "q"; + final int EXPECTED_SPAN_START = 0; + final int EXPECTED_SPAN_END = 5; + type(STRING_1_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + type(STRING_2_TO_TYPE); + // We haven't have time to look into the dictionary yet, so the line should still be + // blue to avoid any flicker. + final Span spanBefore = new Span(mTextView.getText()); + assertEquals("extend blue underline, span start", EXPECTED_SPAN_START, spanBefore.mStart); + assertEquals("extend blue underline, span end", EXPECTED_SPAN_END, spanBefore.mEnd); + assertEquals("extend blue underline, span color", true, + spanBefore.isAutoCorrectionIndicator()); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + // Now we have been able to re-evaluate the word, there shouldn't be an auto-correction span + final Span spanAfter = new Span(mTextView.getText()); + assertNull("hide blue underline", spanAfter.mSpan); + } + + public void testBlueUnderlineOnBackspace() { + final String STRING_TO_TYPE = "tgis"; + final int EXPECTED_SPAN_START = 0; + final int EXPECTED_SPAN_END = 4; + type(STRING_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + type(Keyboard.CODE_SPACE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + type(Keyboard.CODE_DELETE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + type(Keyboard.CODE_DELETE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + final Span span = new Span(mTextView.getText()); + assertEquals("show blue underline after backspace, span start", + EXPECTED_SPAN_START, span.mStart); + assertEquals("show blue underline after backspace, span end", + EXPECTED_SPAN_END, span.mEnd); + assertEquals("show blue underline after backspace, span color", true, + span.isAutoCorrectionIndicator()); + } + + public void testBlueUnderlineDisappearsWhenCursorMoved() { + final String STRING_TO_TYPE = "tgis"; + final int NEW_CURSOR_POSITION = 0; + type(STRING_TO_TYPE); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + // Simulate the onUpdateSelection() event + mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1); + runMessages(); + // Here the blue underline has been set. testBlueUnderline() is testing for this already, + // so let's not test it here again. + // Now simulate the user moving the cursor. + mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION); + mLatinIME.onUpdateSelection(0, 0, NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1); + sleep(DELAY_TO_WAIT_FOR_UNDERLINE); + runMessages(); + final Span span = new Span(mTextView.getText()); + assertNull("blue underline removed when cursor is moved", span.mSpan); + } + // TODO: Add some tests for non-BMP characters +} diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java index fec3e8ee1..7925d1a49 100644 --- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java +++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java @@ -16,10 +16,7 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.latin.LocaleUtils; - import android.content.Context; -import android.content.res.Resources; import android.test.AndroidTestCase; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -30,24 +27,22 @@ import java.util.List; import java.util.Locale; public class SubtypeLocaleTests extends AndroidTestCase { - private static final String PACKAGE = LatinIME.class.getPackage().getName(); - - private Resources mRes; - private List<InputMethodSubtype> mKeyboardSubtypes = new ArrayList<InputMethodSubtype>(); + private List<InputMethodSubtype> mKeyboardSubtypes; @Override protected void setUp() throws Exception { super.setUp(); final Context context = getContext(); - mRes = context.getResources(); + final String packageName = context.getApplicationInfo().packageName; SubtypeLocale.init(context); final InputMethodManager imm = (InputMethodManager) context.getSystemService( Context.INPUT_METHOD_SERVICE); for (final InputMethodInfo imi : imm.getInputMethodList()) { - if (imi.getPackageName().equals(PACKAGE)) { + if (imi.getPackageName().equals(packageName)) { + mKeyboardSubtypes = new ArrayList<InputMethodSubtype>(); final int subtypeCount = imi.getSubtypeCount(); for (int i = 0; i < subtypeCount; ++i) { InputMethodSubtype subtype = imi.getSubtypeAt(i); @@ -58,37 +53,29 @@ public class SubtypeLocaleTests extends AndroidTestCase { break; } } - assertNotNull("Can not find input method " + PACKAGE, mKeyboardSubtypes); + assertNotNull("Can not find input method " + packageName, mKeyboardSubtypes); assertTrue("Can not find keyboard subtype", mKeyboardSubtypes.size() > 0); } - private String getStringWithLocale(int resId, Locale locale) { - final Locale savedLocale = Locale.getDefault(); - try { - Locale.setDefault(locale); - return mRes.getString(resId); - } finally { - Locale.setDefault(savedLocale); - } - } - public void testSubtypeLocale() { final StringBuilder messages = new StringBuilder(); int failedCount = 0; for (final InputMethodSubtype subtype : mKeyboardSubtypes) { - final String localeCode = subtype.getLocale(); - final Locale locale = LocaleUtils.constructLocaleFromString(localeCode); - // The locale name which will be displayed on spacebar. For example 'English (US)' or - // 'Francais (Canada)'. (c=\u008d) - final String displayName = SubtypeLocale.getFullDisplayName(locale); - // The subtype name in its locale. For example 'English (US) Keyboard' or - // 'Clavier Francais (Canada)'. (c=\u008d) - final String subtypeName = getStringWithLocale(subtype.getNameResId(), locale); - if (subtypeName.contains(displayName)) { + final Locale locale = LocaleUtils.constructLocaleFromString(subtype.getLocale()); + final String subtypeLocaleString = + subtype.containsExtraValueKey(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE) + ? subtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE) + : subtype.getLocale(); + final Locale subtypeLocale = LocaleUtils.constructLocaleFromString(subtypeLocaleString); + // The subtype name in its locale. For example 'English (US)' or 'Deutsch (QWERTY)'. + final String subtypeName = SubtypeLocale.getFullDisplayName(subtypeLocale); + // The locale language name in its locale. + final String languageName = locale.getDisplayLanguage(locale); + if (!subtypeName.contains(languageName)) { failedCount++; messages.append(String.format( - "subtype name is '%s' and should contain locale '%s' name '%s'\n", - subtypeName, localeCode, displayName)); + "subtype name is '%s' and should contain locale '%s' language name '%s'\n", + subtypeName, subtypeLocale, languageName)); } } assertEquals(messages.toString(), 0, failedCount); diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java deleted file mode 100644 index 464930f4c..000000000 --- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.latin; - -import android.content.Context; -import android.text.TextUtils; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.KeyDetector; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.keyboard.LatinKeyboard; - -import java.io.File; -import java.util.Locale; - -public class SuggestHelper { - protected final Suggest mSuggest; - protected final LatinKeyboard mKeyboard; - private final KeyDetector mKeyDetector; - - public SuggestHelper(Context context, int dictionaryId, KeyboardId keyboardId) { - // Use null as the locale for Suggest so as to force it to use the internal dictionary - // (and not try to find a dictionary provider for a specified locale) - mSuggest = new Suggest(context, dictionaryId, null); - mKeyboard = new LatinKeyboard.Builder(context).load(keyboardId).build(); - mKeyDetector = new KeyDetector(0); - init(); - } - - protected SuggestHelper(final Context context, final File dictionaryPath, - final long startOffset, final long length, final KeyboardId keyboardId, - final Locale locale) { - mSuggest = new Suggest(context, dictionaryPath, startOffset, length, null, locale); - mKeyboard = new LatinKeyboard.Builder(context).load(keyboardId).build(); - mKeyDetector = new KeyDetector(0); - init(); - } - - private void init() { - mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL); - mKeyDetector.setKeyboard(mKeyboard, 0, 0); - mKeyDetector.setProximityCorrectionEnabled(true); - mKeyDetector.setProximityThreshold(mKeyboard.mMostCommonKeyWidth); - } - - public void setCorrectionMode(int correctionMode) { - mSuggest.setCorrectionMode(correctionMode); - } - - public boolean hasMainDictionary() { - return mSuggest.hasMainDictionary(); - } - - private void addKeyInfo(WordComposer word, char c) { - for (final Key key : mKeyboard.mKeys) { - if (key.mCode == c) { - final int x = key.mX + key.mWidth / 2; - final int y = key.mY + key.mHeight / 2; - final int[] codes = mKeyDetector.newCodeArray(); - mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); - word.add(c, codes, x, y); - return; - } - } - word.add(c, new int[] { c }, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); - } - - protected WordComposer createWordComposer(CharSequence s) { - WordComposer word = new WordComposer(); - for (int i = 0; i < s.length(); i++) { - final char c = s.charAt(i); - addKeyInfo(word, c); - } - return word; - } - - public boolean isValidWord(CharSequence typed) { - return AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), - typed, false); - } - - // TODO: This may be slow, but is OK for test so far. - public SuggestedWords getSuggestions(CharSequence typed) { - return mSuggest.getSuggestions(createWordComposer(typed), null, - mKeyboard.getProximityInfo()); - } - - public CharSequence getFirstSuggestion(CharSequence typed) { - WordComposer word = createWordComposer(typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, null, - mKeyboard.getProximityInfo()); - // Note that suggestions.getWord(0) is the word user typed. - return suggestions.size() > 1 ? suggestions.getWord(1) : null; - } - - public CharSequence getAutoCorrection(CharSequence typed) { - WordComposer word = createWordComposer(typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, null, - mKeyboard.getProximityInfo()); - // Note that suggestions.getWord(0) is the word user typed. - return (suggestions.size() > 1 && mSuggest.hasAutoCorrection()) - ? suggestions.getWord(1) : null; - } - - public int getSuggestIndex(CharSequence typed, CharSequence expected) { - WordComposer word = createWordComposer(typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, null, - mKeyboard.getProximityInfo()); - // Note that suggestions.getWord(0) is the word user typed. - for (int i = 1; i < suggestions.size(); i++) { - if (TextUtils.equals(suggestions.getWord(i), expected)) - return i; - } - return -1; - } - - private void getBigramSuggestions(CharSequence previous, CharSequence typed) { - if (!TextUtils.isEmpty(previous) && (typed.length() > 1)) { - WordComposer firstChar = createWordComposer(Character.toString(typed.charAt(0))); - mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo()); - } - } - - public CharSequence getBigramFirstSuggestion(CharSequence previous, CharSequence typed) { - WordComposer word = createWordComposer(typed); - getBigramSuggestions(previous, typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, previous, - mKeyboard.getProximityInfo()); - return suggestions.size() > 1 ? suggestions.getWord(1) : null; - } - - public CharSequence getBigramAutoCorrection(CharSequence previous, CharSequence typed) { - WordComposer word = createWordComposer(typed); - getBigramSuggestions(previous, typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, previous, - mKeyboard.getProximityInfo()); - return (suggestions.size() > 1 && mSuggest.hasAutoCorrection()) - ? suggestions.getWord(1) : null; - } - - public int searchBigramSuggestion(CharSequence previous, CharSequence typed, - CharSequence expected) { - WordComposer word = createWordComposer(typed); - getBigramSuggestions(previous, typed); - SuggestedWords suggestions = mSuggest.getSuggestions(word, previous, - mKeyboard.getProximityInfo()); - for (int i = 1; i < suggestions.size(); i++) { - if (TextUtils.equals(suggestions.getWord(i), expected)) - return i; - } - return -1; - } -} diff --git a/tests/src/com/android/inputmethod/latin/SuggestTests.java b/tests/src/com/android/inputmethod/latin/SuggestTests.java deleted file mode 100644 index 4080f34be..000000000 --- a/tests/src/com/android/inputmethod/latin/SuggestTests.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2010,2011 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 com.android.inputmethod.latin.tests.R; - -import android.content.res.AssetFileDescriptor; -import android.content.res.Configuration; - -import java.util.Locale; - -public class SuggestTests extends SuggestTestsBase { - private SuggestHelper mHelper; - - @Override - protected void setUp() throws Exception { - super.setUp(); - final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test); - final Locale locale = Locale.US; - mHelper = new SuggestHelper( - getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(), - createKeyboardId(locale, Configuration.ORIENTATION_PORTRAIT), locale); - mHelper.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM); - } - - /************************** Tests ************************/ - - /** - * Tests for simple completions of one character. - */ - public void testCompletion1char() { - suggested("people", mHelper.getFirstSuggestion("peopl")); - suggested("about", mHelper.getFirstSuggestion("abou")); - suggested("their", mHelper.getFirstSuggestion("thei")); - } - - /** - * Tests for simple completions of two characters. - */ - public void testCompletion2char() { - suggested("people", mHelper.getFirstSuggestion("peop")); - suggested("calling", mHelper.getFirstSuggestion("calli")); - suggested("business", mHelper.getFirstSuggestion("busine")); - } - - /** - * Tests for proximity errors. - */ - public void testProximityPositive() { - suggested("typed peiple", "people", mHelper.getFirstSuggestion("peiple")); - suggested("typed peoole", "people", mHelper.getFirstSuggestion("peoole")); - suggested("typed pwpple", "people", mHelper.getFirstSuggestion("pwpple")); - } - - /** - * Tests for proximity errors - negative, when the error key is not close. - */ - public void testProximityNegative() { - notSuggested("about", mHelper.getFirstSuggestion("arout")); - notSuggested("are", mHelper.getFirstSuggestion("ire")); - } - - /** - * Tests for checking if apostrophes are added automatically. - */ - public void testApostropheInsertion() { - suggested("I'm", mHelper.getFirstSuggestion("im")); - suggested("don't", mHelper.getFirstSuggestion("dont")); - } - - /** - * Test to make sure apostrophed word is not suggested for an apostrophed word. - */ - public void testApostrophe() { - notSuggested("don't", mHelper.getFirstSuggestion("don't")); - } - - /** - * Tests for suggestion of capitalized version of a word. - */ - public void testCapitalization() { - suggested("I'm", mHelper.getFirstSuggestion("i'm")); - suggested("Sunday", mHelper.getFirstSuggestion("sunday")); - suggested("Sunday", mHelper.getFirstSuggestion("sundat")); - } - - /** - * Tests to see if more than one completion is provided for certain prefixes. - */ - public void testMultipleCompletions() { - isInSuggestions("com: come", mHelper.getSuggestIndex("com", "come")); - isInSuggestions("com: company", mHelper.getSuggestIndex("com", "company")); - isInSuggestions("th: the", mHelper.getSuggestIndex("th", "the")); - isInSuggestions("th: that", mHelper.getSuggestIndex("th", "that")); - isInSuggestions("th: this", mHelper.getSuggestIndex("th", "this")); - isInSuggestions("th: they", mHelper.getSuggestIndex("th", "they")); - } - - /** - * Does the suggestion engine recognize zero frequency words as valid words. - */ - public void testZeroFrequencyAccepted() { - assertTrue("valid word yikes", mHelper.isValidWord("yikes")); - assertFalse("non valid word yike", mHelper.isValidWord("yike")); - } - - /** - * Tests to make sure that zero frequency words are not suggested as completions. - */ - public void testZeroFrequencySuggestionsNegative() { - assertTrue(mHelper.getSuggestIndex("yike", "yikes") < 0); - assertTrue(mHelper.getSuggestIndex("what", "whatcha") < 0); - } - - /** - * Tests to ensure that words with large edit distances are not suggested, in some cases. - * Also such word is not considered auto correction, in some cases. - */ - public void testTooLargeEditDistance() { - assertTrue(mHelper.getSuggestIndex("sniyr", "about") < 0); - // TODO: The following test fails. - // notSuggested("the", mHelper.getAutoCorrection("rjw")); - } - - /** - * Make sure mHelper.isValidWord is case-sensitive. - */ - public void testValidityCaseSensitivity() { - assertTrue("valid word Sunday", mHelper.isValidWord("Sunday")); - assertFalse("non valid word sunday", mHelper.isValidWord("sunday")); - } - - /** - * Are accented forms of words suggested as corrections? - */ - public void testAccents() { - // ni<LATIN SMALL LETTER N WITH TILDE>o - suggested("ni\u00F1o", mHelper.getAutoCorrection("nino")); - // ni<LATIN SMALL LETTER N WITH TILDE>o - suggested("ni\u00F1o", mHelper.getAutoCorrection("nimo")); - // Mar<LATIN SMALL LETTER I WITH ACUTE>a - suggested("Mar\u00EDa", mHelper.getAutoCorrection("maria")); - } - - /** - * Make sure bigrams are showing when first character is typed - * and don't show any when there aren't any - */ - public void testBigramsAtFirstChar() { - suggested("bigram: about p[art]", - "part", mHelper.getBigramFirstSuggestion("about", "p")); - suggested("bigram: I'm a[bout]", - "about", mHelper.getBigramFirstSuggestion("I'm", "a")); - suggested("bigram: about b[usiness]", - "business", mHelper.getBigramFirstSuggestion("about", "b")); - isInSuggestions("bigram: about b[eing]", - mHelper.searchBigramSuggestion("about", "b", "being")); - notSuggested("bigram: about p", - "business", mHelper.getBigramFirstSuggestion("about", "p")); - } - - /** - * Make sure bigrams score affects the original score - */ - public void testBigramsScoreEffect() { - suggested("single: page", - "page", mHelper.getAutoCorrection("pa")); - suggested("bigram: about pa[rt]", - "part", mHelper.getBigramAutoCorrection("about", "pa")); - // TODO: The following test fails. - // suggested("single: said", "said", mHelper.getAutoCorrection("sa")); - suggested("bigram: from sa[me]", - "same", mHelper.getBigramAutoCorrection("from", "sa")); - } -} diff --git a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java b/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java deleted file mode 100644 index 058a3e7c0..000000000 --- a/tests/src/com/android/inputmethod/latin/SuggestTestsBase.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2011 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.res.AssetFileDescriptor; -import android.content.res.Configuration; -import android.test.AndroidTestCase; -import android.text.TextUtils; -import android.util.DisplayMetrics; -import android.view.inputmethod.EditorInfo; - -import com.android.inputmethod.keyboard.KeyboardId; - -import java.io.File; -import java.io.InputStream; -import java.util.Locale; - -public class SuggestTestsBase extends AndroidTestCase { - protected File mTestPackageFile; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mTestPackageFile = new File(getTestContext().getApplicationInfo().sourceDir); - } - - protected KeyboardId createKeyboardId(Locale locale, int orientation) { - final DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); - final int width; - if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - width = Math.max(dm.widthPixels, dm.heightPixels); - } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { - width = Math.min(dm.widthPixels, dm.heightPixels); - } else { - fail("Orientation should be ORIENTATION_LANDSCAPE or ORIENTATION_PORTRAIT: " - + "orientation=" + orientation); - return null; - } - return new KeyboardId(locale.toString() + " keyboard", - com.android.inputmethod.latin.R.xml.kbd_qwerty, locale, orientation, width, - KeyboardId.MODE_TEXT, new EditorInfo(), false, KeyboardId.F2KEY_MODE_NONE, - false, false, false); - } - - protected InputStream openTestRawResource(int resIdInTest) { - return getTestContext().getResources().openRawResource(resIdInTest); - } - - protected AssetFileDescriptor openTestRawResourceFd(int resIdInTest) { - return getTestContext().getResources().openRawResourceFd(resIdInTest); - } - - private static String format(String message, Object expected, Object actual) { - return message + " expected:<" + expected + "> but was:<" + actual + ">"; - } - - protected static void suggested(CharSequence expected, CharSequence actual) { - if (!TextUtils.equals(expected, actual)) - fail(format("assertEquals", expected, actual)); - } - - protected static void suggested(String message, CharSequence expected, CharSequence actual) { - if (!TextUtils.equals(expected, actual)) - fail(format(message, expected, actual)); - } - - protected static void notSuggested(CharSequence expected, CharSequence actual) { - if (TextUtils.equals(expected, actual)) - fail(format("assertNotEquals", expected, actual)); - } - - protected static void notSuggested(String message, CharSequence expected, CharSequence actual) { - if (TextUtils.equals(expected, actual)) - fail(format(message, expected, actual)); - } - - protected static void isInSuggestions(String message, int position) { - assertTrue(message, position >= 0); - } - - protected static void isNotInSuggestions(String message, int position) { - assertTrue(message, position < 0); - } -} diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java deleted file mode 100644 index 023e20a10..000000000 --- a/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.inputmethod.keyboard.KeyboardId; - -import android.content.Context; -import android.text.TextUtils; - -import java.io.File; -import java.util.Locale; -import java.util.StringTokenizer; - -public class UserBigramSuggestHelper extends SuggestHelper { - private final Context mContext; - private UserBigramDictionary mUserBigram; - - public UserBigramSuggestHelper(final Context context, final File dictionaryPath, - final long startOffset, final long length, final int userBigramMax, - final int userBigramDelete, final KeyboardId keyboardId, final Locale locale) { - super(context, dictionaryPath, startOffset, length, keyboardId, locale); - mContext = context; - mUserBigram = new UserBigramDictionary(context, null, locale.toString(), - Suggest.DIC_USER); - mUserBigram.setDatabaseMax(userBigramMax); - mUserBigram.setDatabaseDelete(userBigramDelete); - mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM); - mSuggest.setUserBigramDictionary(mUserBigram); - } - - public void changeUserBigramLocale(Locale locale) { - if (mUserBigram != null) { - flushUserBigrams(); - mUserBigram.close(); - mUserBigram = new UserBigramDictionary(mContext, null, locale.toString(), - Suggest.DIC_USER); - mSuggest.setUserBigramDictionary(mUserBigram); - } - } - - public int searchUserBigramSuggestion(CharSequence previous, char typed, - CharSequence expected) { - if (mUserBigram == null) return -1; - - flushUserBigrams(); - if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) { - WordComposer firstChar = createWordComposer(Character.toString(typed)); - mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo()); - boolean reloading = mUserBigram.reloadDictionaryIfRequired(); - if (reloading) mUserBigram.waitForDictionaryLoading(); - mUserBigram.getBigrams(firstChar, previous, mSuggest); - } - - for (int i = 0; i < mSuggest.mBigramSuggestions.size(); i++) { - final CharSequence word = mSuggest.mBigramSuggestions.get(i); - if (TextUtils.equals(word, expected)) - return i; - } - - return -1; - } - - public void addToUserBigram(String sentence) { - StringTokenizer st = new StringTokenizer(sentence); - String previous = null; - while (st.hasMoreTokens()) { - String current = st.nextToken(); - if (previous != null) { - addToUserBigram(new String[] {previous, current}); - } - previous = current; - } - } - - public void addToUserBigram(String[] pair) { - if (mUserBigram != null && pair.length == 2) { - mUserBigram.addBigrams(pair[0], pair[1]); - } - } - - public void flushUserBigrams() { - if (mUserBigram != null) { - mUserBigram.flushPendingWrites(); - mUserBigram.waitUntilUpdateDBDone(); - } - } -} diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java deleted file mode 100644 index 2bc0aabc0..000000000 --- a/tests/src/com/android/inputmethod/latin/UserBigramSuggestTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010,2011 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.res.AssetFileDescriptor; -import android.content.res.Configuration; - -import com.android.inputmethod.latin.tests.R; - -import java.util.Locale; - -public class UserBigramSuggestTests extends SuggestTestsBase { - private static final int SUGGESTION_STARTS = 6; - private static final int MAX_DATA = 20; - private static final int DELETE_DATA = 10; - - private UserBigramSuggestHelper mHelper; - - @Override - protected void setUp() throws Exception { - super.setUp(); - final AssetFileDescriptor dict = openTestRawResourceFd(R.raw.test); - final Locale locale = Locale.US; - mHelper = new UserBigramSuggestHelper( - getContext(), mTestPackageFile, dict.getStartOffset(), dict.getLength(), - MAX_DATA, DELETE_DATA, - createKeyboardId(locale, Configuration.ORIENTATION_PORTRAIT), locale); - } - - /************************** Tests ************************/ - - /** - * Test suggestion started at right time - */ - public void testUserBigram() { - for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair1); - for (int i = 0; i < (SUGGESTION_STARTS - 1); i++) mHelper.addToUserBigram(pair2); - - isInSuggestions("bigram", mHelper.searchUserBigramSuggestion("user", 'b', "bigram")); - isNotInSuggestions("platform", - mHelper.searchUserBigramSuggestion("android", 'p', "platform")); - } - - /** - * Test loading correct (locale) bigrams - */ - public void testOpenAndClose() { - for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair1); - isInSuggestions("bigram in default locale", - mHelper.searchUserBigramSuggestion("user", 'b', "bigram")); - - // change to fr_FR - mHelper.changeUserBigramLocale(Locale.FRANCE); - for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(pair3); - isInSuggestions("france in fr_FR", - mHelper.searchUserBigramSuggestion("locale", 'f', "france")); - isNotInSuggestions("bigram in fr_FR", - mHelper.searchUserBigramSuggestion("user", 'b', "bigram")); - - // change back to en_US - mHelper.changeUserBigramLocale(Locale.US); - isNotInSuggestions("france in en_US", - mHelper.searchUserBigramSuggestion("locale", 'f', "france")); - isInSuggestions("bigram in en_US", - mHelper.searchUserBigramSuggestion("user", 'b', "bigram")); - } - - /** - * Test data gets pruned when it is over maximum - */ - public void testPruningData() { - for (int i = 0; i < SUGGESTION_STARTS; i++) mHelper.addToUserBigram(sentence0); - mHelper.flushUserBigrams(); - isInSuggestions("world after several sentence 0", - mHelper.searchUserBigramSuggestion("Hello", 'w', "world")); - - mHelper.addToUserBigram(sentence1); - mHelper.addToUserBigram(sentence2); - isInSuggestions("world after sentence 1 and 2", - mHelper.searchUserBigramSuggestion("Hello", 'w', "world")); - - // pruning should happen - mHelper.addToUserBigram(sentence3); - mHelper.addToUserBigram(sentence4); - - // trying to reopen database to check pruning happened in database - mHelper.changeUserBigramLocale(Locale.US); - isNotInSuggestions("world after sentence 3 and 4", - mHelper.searchUserBigramSuggestion("Hello", 'w', "world")); - } - - private static final String[] pair1 = {"user", "bigram"}; - private static final String[] pair2 = {"android","platform"}; - private static final String[] pair3 = {"locale", "france"}; - private static final String sentence0 = "Hello world"; - private static final String sentence1 = "This is a test for user input based bigram"; - private static final String sentence2 = "It learns phrases that contain both dictionary and " - + "nondictionary words"; - private static final String sentence3 = "This should give better suggestions than the previous " - + "version"; - private static final String sentence4 = "Android stock keyboard is improving"; -} diff --git a/tests/src/com/android/inputmethod/latin/UtilsTests.java b/tests/src/com/android/inputmethod/latin/UtilsTests.java index 5c0b03a0a..2ef4e2ff5 100644 --- a/tests/src/com/android/inputmethod/latin/UtilsTests.java +++ b/tests/src/com/android/inputmethod/latin/UtilsTests.java @@ -18,8 +18,6 @@ package com.android.inputmethod.latin; import android.test.AndroidTestCase; -import com.android.inputmethod.latin.tests.R; - public class UtilsTests extends AndroidTestCase { // The following is meant to be a reasonable default for diff --git a/tools/Android.mk b/tools/Android.mk index 8f1acc55a..91b2fbbb0 100644 --- a/tools/Android.mk +++ b/tools/Android.mk @@ -12,6 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -LOCAL_PATH := $(call my-dir) - -include $(call all-makefiles-under,$(LOCAL_PATH)) +include $(call all-subdir-makefiles) diff --git a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java index 92f402d3e..485dba10b 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java +++ b/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.Map; import java.util.TreeMap; @@ -44,8 +45,9 @@ public class BinaryDictInputOutput { * a | 11 = 3 bytes : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES * g | has several chars ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_MULTIPLE_CHARS * s | has a terminal ? 1 bit, 1 = yes, 0 = no : FLAG_IS_TERMINAL - * | reserved 1 bit, 1 = yes, 0 = no + * | has shortcut targets ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_SHORTCUT_TARGETS * | has bigrams ? 1 bit, 1 = yes, 0 = no : FLAG_HAS_BIGRAMS + * | is shortcut only ? 1 bit, 1 = yes, 0 = no : FLAG_IS_SHORTCUT_ONLY * * c | IF FLAG_HAS_MULTIPLE_CHARS * h | char, char, char, char n * (1 or 3 bytes) : use CharGroupInfo for i/o helpers @@ -71,6 +73,8 @@ public class BinaryDictInputOutput { * d * dress * + * | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS + * | shortcut targets address list * | IF FLAG_IS_TERMINAL && FLAG_HAS_BIGRAMS * | bigrams address list * @@ -107,9 +111,13 @@ public class BinaryDictInputOutput { * */ - private static final int MAGIC_NUMBER = 0x78B1; - private static final int VERSION = 1; - private static final int MAXIMUM_SUPPORTED_VERSION = VERSION; + private static final int VERSION_1_MAGIC_NUMBER = 0x78B1; + private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; + private static final int MINIMUM_SUPPORTED_VERSION = 1; + private static final int MAXIMUM_SUPPORTED_VERSION = 2; + private static final int NOT_A_VERSION_NUMBER = -1; + private static final int FIRST_VERSION_WITH_HEADER_SIZE = 2; + // No options yet, reserved for future use. private static final int OPTIONS = 0; @@ -126,7 +134,9 @@ public class BinaryDictInputOutput { private static final int FLAG_HAS_MULTIPLE_CHARS = 0x20; private static final int FLAG_IS_TERMINAL = 0x10; + private static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08; private static final int FLAG_HAS_BIGRAMS = 0x04; + private static final int FLAG_IS_SHORTCUT_ONLY = 0x02; private static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80; private static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40; @@ -138,7 +148,6 @@ public class BinaryDictInputOutput { private static final int GROUP_CHARACTERS_TERMINATOR = 0x1F; - private static final int GROUP_COUNT_SIZE = 1; private static final int GROUP_TERMINATOR_SIZE = 1; private static final int GROUP_FLAGS_SIZE = 1; private static final int GROUP_FREQUENCY_SIZE = 1; @@ -149,9 +158,8 @@ public class BinaryDictInputOutput { private static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE; private static final int INVALID_CHARACTER = -1; - // Limiting to 127 for upward compatibility - // TODO: implement a scheme to be able to shoot 256 chargroups in a node - private static final int MAX_CHARGROUPS_IN_A_NODE = 127; + private static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127 + private static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767 private static final int MAX_TERMINAL_FREQUENCY = 255; @@ -261,6 +269,31 @@ public class BinaryDictInputOutput { } /** + * Compute the binary size of the group count + * @param count the group count + * @return the size of the group count, either 1 or 2 bytes. + */ + private static int getGroupCountSize(final int count) { + if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= count) { + return 1; + } else if (MAX_CHARGROUPS_IN_A_NODE >= count) { + return 2; + } else { + throw new RuntimeException("Can't have more than " + MAX_CHARGROUPS_IN_A_NODE + + " groups in a node (found " + count +")"); + } + } + + /** + * Compute the binary size of the group count for a node + * @param node the node + * @return the size of the group count, either 1 or 2 bytes. + */ + private static int getGroupCountSize(final Node node) { + return getGroupCountSize(node.mData.size()); + } + + /** * Compute the maximum size of a CharGroup, assuming 3-byte addresses for everything. * * @param group the CharGroup to compute the size of. @@ -271,10 +304,13 @@ public class BinaryDictInputOutput { // If terminal, one byte for the frequency if (group.isTerminal()) size += GROUP_FREQUENCY_SIZE; size += GROUP_MAX_ADDRESS_SIZE; // For children address + if (null != group.mShortcutTargets) { + size += (GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE) + * group.mShortcutTargets.size(); + } if (null != group.mBigrams) { - for (WeightedString bigram : group.mBigrams) { - size += GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE; - } + size += (GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE) + * group.mBigrams.size(); } return size; } @@ -286,7 +322,7 @@ public class BinaryDictInputOutput { * @param node the node to compute the maximum size of. */ private static void setNodeMaximumSize(Node node) { - int size = GROUP_COUNT_SIZE; + int size = getGroupCountSize(node); for (CharGroup g : node.mData) { final int groupSize = getCharGroupMaximumSize(g); g.mCachedSize = groupSize; @@ -303,6 +339,13 @@ public class BinaryDictInputOutput { } /** + * Helper method to find out if a character info is a shortcut only. + */ + private static boolean isShortcutOnly(final CharGroupInfo info) { + return 0 != (info.mFlags & FLAG_IS_SHORTCUT_ONLY); + } + + /** * Compute the size, in bytes, that an address will occupy. * * This can be used either for children addresses (which are always positive) or for @@ -378,7 +421,7 @@ public class BinaryDictInputOutput { * @param dict the dictionary in which the word/attributes are to be found. */ private static void computeActualNodeSize(Node node, FusionDictionary dict) { - int size = GROUP_COUNT_SIZE; + int size = getGroupCountSize(node); for (CharGroup group : node.mData) { int groupSize = GROUP_FLAGS_SIZE + getGroupCharactersSize(group); if (group.isTerminal()) groupSize += GROUP_FREQUENCY_SIZE; @@ -387,6 +430,15 @@ public class BinaryDictInputOutput { final int offset = group.mChildren.mCachedAddress - offsetBasePoint; groupSize += getByteSize(offset); } + if (null != group.mShortcutTargets) { + for (WeightedString target : group.mShortcutTargets) { + final int offsetBasePoint = groupSize + node.mCachedAddress + size + + GROUP_FLAGS_SIZE; + final int addressOfTarget = findAddressOfWord(dict, target.mWord); + final int offset = addressOfTarget - offsetBasePoint; + groupSize += getByteSize(offset) + GROUP_FLAGS_SIZE; + } + } if (null != group.mBigrams) { for (WeightedString bigram : group.mBigrams) { final int offsetBasePoint = groupSize + node.mCachedAddress + size @@ -412,12 +464,13 @@ public class BinaryDictInputOutput { int nodeOffset = 0; for (Node n : flatNodes) { n.mCachedAddress = nodeOffset; + int groupCountSize = getGroupCountSize(n); int groupOffset = 0; for (CharGroup g : n.mData) { - g.mCachedAddress = GROUP_COUNT_SIZE + nodeOffset + groupOffset; + g.mCachedAddress = groupCountSize + nodeOffset + groupOffset; groupOffset += g.mCachedSize; } - if (groupOffset + GROUP_COUNT_SIZE != n.mCachedSize) { + if (groupOffset + groupCountSize != n.mCachedSize) { throw new RuntimeException("Bug : Stored and computed node size differ"); } nodeOffset += n.mCachedSize; @@ -545,7 +598,21 @@ public class BinaryDictInputOutput { throw new RuntimeException("Node with a strange address"); } } - if (null != group.mBigrams) flags |= FLAG_HAS_BIGRAMS; + if (null != group.mShortcutTargets) { + if (0 == group.mShortcutTargets.size()) { + throw new RuntimeException("0-sized shortcut list must be null"); + } + flags |= FLAG_HAS_SHORTCUT_TARGETS; + } + if (null != group.mBigrams) { + if (0 == group.mBigrams.size()) { + throw new RuntimeException("0-sized bigram list must be null"); + } + flags |= FLAG_HAS_BIGRAMS; + } + if (group.mIsShortcutOnly) { + flags |= FLAG_IS_SHORTCUT_ONLY; + } return flags; } @@ -592,13 +659,20 @@ public class BinaryDictInputOutput { private static int writePlacedNode(FusionDictionary dict, byte[] buffer, Node node) { int index = node.mCachedAddress; - final int size = node.mData.size(); - if (size > MAX_CHARGROUPS_IN_A_NODE) - throw new RuntimeException("A node has a group count over 127 (" + size + ")."); - - buffer[index++] = (byte)size; + final int groupCount = node.mData.size(); + final int countSize = getGroupCountSize(node); + if (1 == countSize) { + buffer[index++] = (byte)groupCount; + } else if (2 == countSize) { + // We need to signal 2-byte size by setting the top bit of the MSB to 1, so + // we | 0x80 to do this. + buffer[index++] = (byte)((groupCount >> 8) | 0x80); + buffer[index++] = (byte)(groupCount & 0xFF); + } else { + throw new RuntimeException("Strange size from getGroupCountSize : " + countSize); + } int groupAddress = index; - for (int i = 0; i < size; ++i) { + for (int i = 0; i < groupCount; ++i) { CharGroup group = node.mData.get(i); if (index != group.mCachedAddress) throw new RuntimeException("Bug: write index is not " + "the same as the cached address of the group"); @@ -624,20 +698,36 @@ public class BinaryDictInputOutput { index += shift; groupAddress += shift; + // Write shortcuts + if (null != group.mShortcutTargets) { + final Iterator shortcutIterator = group.mShortcutTargets.iterator(); + while (shortcutIterator.hasNext()) { + final WeightedString target = (WeightedString)shortcutIterator.next(); + final int addressOfTarget = findAddressOfWord(dict, target.mWord); + ++groupAddress; + final int offset = addressOfTarget - groupAddress; + int shortcutFlags = makeAttributeFlags(shortcutIterator.hasNext(), offset, + target.mFrequency); + buffer[index++] = (byte)shortcutFlags; + final int shortcutShift = writeVariableAddress(buffer, index, Math.abs(offset)); + index += shortcutShift; + groupAddress += shortcutShift; + } + } // Write bigrams if (null != group.mBigrams) { - int remainingBigrams = group.mBigrams.size(); - for (WeightedString bigram : group.mBigrams) { - boolean more = remainingBigrams > 1; + final Iterator bigramIterator = group.mBigrams.iterator(); + while (bigramIterator.hasNext()) { + final WeightedString bigram = (WeightedString)bigramIterator.next(); final int addressOfBigram = findAddressOfWord(dict, bigram.mWord); ++groupAddress; final int offset = addressOfBigram - groupAddress; - int bigramFlags = makeAttributeFlags(more, offset, bigram.mFrequency); + int bigramFlags = makeAttributeFlags(bigramIterator.hasNext(), offset, + bigram.mFrequency); buffer[index++] = (byte)bigramFlags; final int bigramShift = writeVariableAddress(buffer, index, Math.abs(offset)); index += bigramShift; groupAddress += bigramShift; - --remainingBigrams; } } @@ -711,9 +801,11 @@ public class BinaryDictInputOutput { * * @param destination the stream to write the binary data to. * @param dict the dictionary to write. + * @param version the version of the format to write, currently either 1 or 2. */ - public static void writeDictionaryBinary(OutputStream destination, FusionDictionary dict) - throws IOException { + public static void writeDictionaryBinary(final OutputStream destination, + final FusionDictionary dict, final int version) + throws IOException, UnsupportedFormatException { // Addresses are limited to 3 bytes, so we'll just make a 16MB buffer. Since addresses // can be relative to each node, the structure itself is not limited to 16MB at all, but @@ -725,16 +817,42 @@ public class BinaryDictInputOutput { final byte[] buffer = new byte[1 << 24]; int index = 0; - // Magic number in big-endian order. - buffer[index++] = (byte) (0xFF & (MAGIC_NUMBER >> 8)); - buffer[index++] = (byte) (0xFF & MAGIC_NUMBER); - // Dictionary version. - buffer[index++] = (byte) (0xFF & VERSION); + if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION) { + throw new UnsupportedFormatException("Requested file format version " + version + + ", but this implementation only supports versions " + + MINIMUM_SUPPORTED_VERSION + " through " + MAXIMUM_SUPPORTED_VERSION); + } + + // The magic number in big-endian order. + if (version >= FIRST_VERSION_WITH_HEADER_SIZE) { + // Magic number for version 2+. + buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 24)); + buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16)); + buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8)); + buffer[index++] = (byte) (0xFF & VERSION_2_MAGIC_NUMBER); + // Dictionary version. + buffer[index++] = (byte) (0xFF & (version >> 8)); + buffer[index++] = (byte) (0xFF & version); + } else { + // Magic number for version 1. + buffer[index++] = (byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8)); + buffer[index++] = (byte) (0xFF & VERSION_1_MAGIC_NUMBER); + // Dictionary version. + buffer[index++] = (byte) (0xFF & version); + } // Options flags buffer[index++] = (byte) (0xFF & (OPTIONS >> 8)); buffer[index++] = (byte) (0xFF & OPTIONS); - - // Should we include the locale and title of the dictionary ? + if (version >= FIRST_VERSION_WITH_HEADER_SIZE) { + final int headerSizeOffset = index; + index += 4; // Size of the header size + // TODO: Write out the header contents here. + // Write out the header size. + buffer[headerSizeOffset] = (byte) (0xFF & (index >> 24)); + buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 16)); + buffer[headerSizeOffset + 2] = (byte) (0xFF & (index >> 8)); + buffer[headerSizeOffset + 3] = (byte) (0xFF & (index >> 0)); + } destination.write(buffer, 0, index); index = 0; @@ -814,14 +932,43 @@ public class BinaryDictInputOutput { childrenAddress = NO_CHILDREN_ADDRESS; break; } + ArrayList<PendingAttribute> shortcutTargets = null; + if (0 != (flags & FLAG_HAS_SHORTCUT_TARGETS)) { + shortcutTargets = new ArrayList<PendingAttribute>(); + while (true) { + final int targetFlags = source.readUnsignedByte(); + ++addressPointer; + final int sign = 0 == (targetFlags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) ? 1 : -1; + int targetAddress = addressPointer; + switch (targetFlags & MASK_ATTRIBUTE_ADDRESS_TYPE) { + case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE: + targetAddress += sign * source.readUnsignedByte(); + addressPointer += 1; + break; + case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES: + targetAddress += sign * source.readUnsignedShort(); + addressPointer += 2; + break; + case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES: + final int offset = ((source.readUnsignedByte() << 16) + + source.readUnsignedShort()); + targetAddress += sign * offset; + addressPointer += 3; + break; + default: + throw new RuntimeException("Has shortcut targets with no address"); + } + shortcutTargets.add(new PendingAttribute(targetFlags & FLAG_ATTRIBUTE_FREQUENCY, + targetAddress)); + if (0 == (targetFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break; + } + } ArrayList<PendingAttribute> bigrams = null; if (0 != (flags & FLAG_HAS_BIGRAMS)) { bigrams = new ArrayList<PendingAttribute>(); - boolean more = true; - while (more) { - int bigramFlags = source.readUnsignedByte(); + while (true) { + final int bigramFlags = source.readUnsignedByte(); ++addressPointer; - more = (0 != (bigramFlags & FLAG_ATTRIBUTE_HAS_NEXT)); final int sign = 0 == (bigramFlags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) ? 1 : -1; int bigramAddress = addressPointer; switch (bigramFlags & MASK_ATTRIBUTE_ADDRESS_TYPE) { @@ -840,14 +987,28 @@ public class BinaryDictInputOutput { addressPointer += 3; break; default: - throw new RuntimeException("Has attribute with no address"); + throw new RuntimeException("Has bigrams with no address"); } bigrams.add(new PendingAttribute(bigramFlags & FLAG_ATTRIBUTE_FREQUENCY, bigramAddress)); + if (0 == (bigramFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break; } } return new CharGroupInfo(originalGroupAddress, addressPointer, flags, characters, frequency, - childrenAddress, bigrams); + childrenAddress, shortcutTargets, bigrams); + } + + /** + * Reads and returns the char group count out of a file and forwards the pointer. + */ + private static int readCharGroupCount(RandomAccessFile source) throws IOException { + final int msb = source.readUnsignedByte(); + if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= msb) { + return msb; + } else { + return ((MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT & msb) << 8) + + source.readUnsignedByte(); + } } /** @@ -863,8 +1024,8 @@ public class BinaryDictInputOutput { int address) throws IOException { final long originalPointer = source.getFilePointer(); source.seek(headerSize); - final int count = source.readUnsignedByte(); - int groupOffset = 1; // 1 for the group count + final int count = readCharGroupCount(source); + int groupOffset = getGroupCountSize(count); final StringBuilder builder = new StringBuilder(); String result = null; @@ -920,11 +1081,19 @@ public class BinaryDictInputOutput { Map<Integer, Node> reverseNodeMap, Map<Integer, CharGroup> reverseGroupMap) throws IOException { final int nodeOrigin = (int)(source.getFilePointer() - headerSize); - final int count = source.readUnsignedByte(); + final int count = readCharGroupCount(source); final ArrayList<CharGroup> nodeContents = new ArrayList<CharGroup>(); - int groupOffset = nodeOrigin + 1; // 1 byte for the group count + int groupOffset = nodeOrigin + getGroupCountSize(count); for (int i = count; i > 0; --i) { CharGroupInfo info = readCharGroup(source, groupOffset); + ArrayList<WeightedString> shortcutTargets = null; + if (null != info.mShortcutTargets) { + shortcutTargets = new ArrayList<WeightedString>(); + for (PendingAttribute target : info.mShortcutTargets) { + final String word = getWordAtAddress(source, headerSize, target.mAddress); + shortcutTargets.add(new WeightedString(word, target.mFrequency)); + } + } ArrayList<WeightedString> bigrams = null; if (null != info.mBigrams) { bigrams = new ArrayList<WeightedString>(); @@ -942,11 +1111,12 @@ public class BinaryDictInputOutput { source.seek(currentPosition); } nodeContents.add( - new CharGroup(info.mCharacters, bigrams, info.mFrequency, - children)); + new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency, + children, isShortcutOnly(info))); } else { nodeContents.add( - new CharGroup(info.mCharacters, bigrams, info.mFrequency)); + new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency, + isShortcutOnly(info))); } groupOffset = info.mEndAddress; } @@ -957,6 +1127,17 @@ public class BinaryDictInputOutput { } /** + * Helper function to get the binary format version from the header. + */ + private static int getFormatVersion(final RandomAccessFile source) throws IOException { + final int magic_v1 = source.readUnsignedShort(); + if (VERSION_1_MAGIC_NUMBER == magic_v1) return source.readUnsignedByte(); + final int magic_v2 = (magic_v1 << 16) + source.readUnsignedShort(); + if (VERSION_2_MAGIC_NUMBER == magic_v2) return source.readUnsignedShort(); + return NOT_A_VERSION_NUMBER; + } + + /** * Reads a random access file and returns the memory representation of the dictionary. * * This high-level method takes a binary file and reads its contents, populating a @@ -967,18 +1148,11 @@ public class BinaryDictInputOutput { * @param dict an optional dictionary to add words to, or null. * @return the created (or merged) dictionary. */ - public static FusionDictionary readDictionaryBinary(RandomAccessFile source, - FusionDictionary dict) throws IOException, UnsupportedFormatException { - // Check magic number - final int magic = source.readUnsignedShort(); - if (MAGIC_NUMBER != magic) { - throw new UnsupportedFormatException("The magic number in this file does not match " - + "the expected value"); - } - + public static FusionDictionary readDictionaryBinary(final RandomAccessFile source, + final FusionDictionary dict) throws IOException, UnsupportedFormatException { // Check file version - final int version = source.readUnsignedByte(); - if (version > MAXIMUM_SUPPORTED_VERSION) { + final int version = getFormatVersion(source); + if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION ) { throw new UnsupportedFormatException("This file has version " + version + ", but this implementation does not support versions above " + MAXIMUM_SUPPORTED_VERSION); @@ -987,7 +1161,16 @@ public class BinaryDictInputOutput { // Read options source.readUnsignedShort(); - long headerSize = source.getFilePointer(); + final long headerSize; + if (version < FIRST_VERSION_WITH_HEADER_SIZE) { + headerSize = source.getFilePointer(); + } else { + headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16) + + (source.readUnsignedByte() << 8) + source.readUnsignedByte(); + // read the header body + source.seek(headerSize); + } + Map<Integer, Node> reverseNodeMapping = new TreeMap<Integer, Node>(); Map<Integer, CharGroup> reverseGroupMapping = new TreeMap<Integer, CharGroup>(); final Node root = readNode(source, headerSize, reverseNodeMapping, reverseGroupMapping); @@ -996,7 +1179,7 @@ public class BinaryDictInputOutput { new FusionDictionary.DictionaryOptions()); if (null != dict) { for (Word w : dict) { - newDict.add(w.mWord, w.mFrequency, w.mBigrams); + newDict.add(w.mWord, w.mFrequency, w.mShortcutTargets, w.mBigrams); } } @@ -1011,10 +1194,11 @@ public class BinaryDictInputOutput { * @param filename The name of the file to test. * @return true if it's a binary dictionary, false otherwise */ - public static boolean isBinaryDictionary(String filename) { + public static boolean isBinaryDictionary(final String filename) { try { RandomAccessFile f = new RandomAccessFile(filename, "r"); - return MAGIC_NUMBER == f.readUnsignedShort(); + final int version = getFormatVersion(f); + return (version >= MINIMUM_SUPPORTED_VERSION && version <= MAXIMUM_SUPPORTED_VERSION); } catch (FileNotFoundException e) { return false; } catch (IOException e) { diff --git a/tools/makedict/src/com/android/inputmethod/latin/CharGroupInfo.java b/tools/makedict/src/com/android/inputmethod/latin/CharGroupInfo.java index 6badfd13a..759cd452d 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/CharGroupInfo.java +++ b/tools/makedict/src/com/android/inputmethod/latin/CharGroupInfo.java @@ -29,10 +29,12 @@ public class CharGroupInfo { public final int[] mCharacters; public final int mFrequency; public final int mChildrenAddress; + public final ArrayList<PendingAttribute> mShortcutTargets; public final ArrayList<PendingAttribute> mBigrams; public CharGroupInfo(final int originalAddress, final int endAddress, final int flags, final int[] characters, final int frequency, final int childrenAddress, + final ArrayList<PendingAttribute> shortcutTargets, final ArrayList<PendingAttribute> bigrams) { mOriginalAddress = originalAddress; mEndAddress = endAddress; @@ -40,6 +42,7 @@ public class CharGroupInfo { mCharacters = characters; mFrequency = frequency; mChildrenAddress = childrenAddress; + mShortcutTargets = shortcutTargets; mBigrams = bigrams; } } diff --git a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java b/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java index 1ba01075e..fbfa424a0 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java +++ b/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java @@ -39,18 +39,37 @@ public class DictionaryMaker { private final static String OPTION_VERSION_2 = "-2"; private final static String OPTION_INPUT_SOURCE = "-s"; private final static String OPTION_INPUT_BIGRAM_XML = "-b"; + private final static String OPTION_INPUT_SHORTCUT_XML = "-c"; private final static String OPTION_OUTPUT_BINARY = "-d"; + private final static String OPTION_OUTPUT_BINARY_FORMAT_VERSION_1 = "-d1"; private final static String OPTION_OUTPUT_XML = "-x"; private final static String OPTION_HELP = "-h"; public final String mInputBinary; public final String mInputUnigramXml; + public final String mInputShortcutXml; public final String mInputBigramXml; public final String mOutputBinary; + public final String mOutputBinaryFormat1; public final String mOutputXml; - private void checkIntegrity() { + private void checkIntegrity() throws IOException { checkHasExactlyOneInput(); checkHasAtLeastOneOutput(); + checkNotSameFile(mInputBinary, mOutputBinary); + checkNotSameFile(mInputBinary, mOutputBinaryFormat1); + checkNotSameFile(mInputBinary, mOutputXml); + checkNotSameFile(mInputUnigramXml, mOutputBinary); + checkNotSameFile(mInputUnigramXml, mOutputBinaryFormat1); + checkNotSameFile(mInputUnigramXml, mOutputXml); + checkNotSameFile(mInputShortcutXml, mOutputBinary); + checkNotSameFile(mInputShortcutXml, mOutputBinaryFormat1); + checkNotSameFile(mInputShortcutXml, mOutputXml); + checkNotSameFile(mInputBigramXml, mOutputBinary); + checkNotSameFile(mInputBigramXml, mOutputBinaryFormat1); + checkNotSameFile(mInputBigramXml, mOutputXml); + checkNotSameFile(mOutputBinary, mOutputBinaryFormat1); + checkNotSameFile(mOutputBinary, mOutputXml); + checkNotSameFile(mOutputBinaryFormat1, mOutputXml); } private void checkHasExactlyOneInput() { @@ -65,33 +84,50 @@ public class DictionaryMaker { } private void checkHasAtLeastOneOutput() { - if (null == mOutputBinary && null == mOutputXml) { + if (null == mOutputBinary && null == mOutputBinaryFormat1 && null == mOutputXml) { throw new RuntimeException("No output specified"); } } + /** + * Utility method that throws an exception if path1 and path2 point to the same file. + */ + private static void checkNotSameFile(final String path1, final String path2) + throws IOException { + if (null == path1 || null == path2) return; + if (new File(path1).getCanonicalPath().equals(new File(path2).getCanonicalPath())) { + throw new RuntimeException(path1 + " and " + path2 + " are the same file: " + + " refusing to process."); + } + } + private void displayHelp() { MakedictLog.i("Usage: makedict " - + "[-s <unigrams.xml> [-b <bigrams.xml>] | -s <binary input>] " - + " [-d <binary output>] [-x <xml output>] [-2]\n" + + "[-s <unigrams.xml> [-b <bigrams.xml>] [-c <shortcuts.xml>] " + + "| -s <binary input>] [-d <binary output format version 2>] " + + "[-d1 <binary output format version 1>] [-x <xml output>] [-2]\n" + "\n" + " Converts a source dictionary file to one or several outputs.\n" + " Source can be an XML file, with an optional XML bigrams file, or a\n" + " binary dictionary file.\n" - + " Both binary and XML outputs are supported. Both can be output at\n" - + " the same time but outputting several files of the same type is not\n" - + " supported."); + + " Binary version 1 (Ice Cream Sandwich), 2 (Jelly Bean) and XML outputs\n" + + " are supported. All three can be output at the same time, but the same\n" + + " output format cannot be specified several times. The behavior is\n" + + " unspecified if the same file is specified for input and output, or for\n" + + " several outputs."); } - public Arguments(String[] argsArray) { + public Arguments(String[] argsArray) throws IOException { final LinkedList<String> args = new LinkedList<String>(Arrays.asList(argsArray)); if (args.isEmpty()) { displayHelp(); } String inputBinary = null; String inputUnigramXml = null; + String inputShortcutXml = null; String inputBigramXml = null; String outputBinary = null; + String outputBinaryFormat1 = null; String outputXml = null; while (!args.isEmpty()) { @@ -105,7 +141,8 @@ public class DictionaryMaker { } else { // All these options need an argument if (args.isEmpty()) { - throw new RuntimeException("Option " + arg + " requires an argument"); + throw new IllegalArgumentException("Option " + arg + " is unknown or " + + "requires an argument"); } String filename = args.get(0); args.remove(0); @@ -115,12 +152,18 @@ public class DictionaryMaker { } else { inputUnigramXml = filename; } + } else if (OPTION_INPUT_SHORTCUT_XML.equals(arg)) { + inputShortcutXml = filename; } else if (OPTION_INPUT_BIGRAM_XML.equals(arg)) { inputBigramXml = filename; } else if (OPTION_OUTPUT_BINARY.equals(arg)) { outputBinary = filename; + } else if (OPTION_OUTPUT_BINARY_FORMAT_VERSION_1.equals(arg)) { + outputBinaryFormat1 = filename; } else if (OPTION_OUTPUT_XML.equals(arg)) { outputXml = filename; + } else { + throw new IllegalArgumentException("Unknown option : " + arg); } } } else { @@ -133,15 +176,17 @@ public class DictionaryMaker { } else if (null == outputBinary) { outputBinary = arg; } else { - throw new RuntimeException("Several output binary files specified"); + throw new IllegalArgumentException("Several output binary files specified"); } } } mInputBinary = inputBinary; mInputUnigramXml = inputUnigramXml; + mInputShortcutXml = inputShortcutXml; mInputBigramXml = inputBigramXml; mOutputBinary = outputBinary; + mOutputBinaryFormat1 = outputBinaryFormat1; mOutputXml = outputXml; checkIntegrity(); } @@ -167,7 +212,7 @@ public class DictionaryMaker { if (null != args.mInputBinary) { return readBinaryFile(args.mInputBinary); } else if (null != args.mInputUnigramXml) { - return readXmlFile(args.mInputUnigramXml, args.mInputBigramXml); + return readXmlFile(args.mInputUnigramXml, args.mInputShortcutXml, args.mInputBigramXml); } else { throw new RuntimeException("No input file specified"); } @@ -192,6 +237,7 @@ public class DictionaryMaker { * Read a dictionary from a unigram XML file, and optionally a bigram XML file. * * @param unigramXmlFilename the name of the unigram XML file. May not be null. + * @param shortcutXmlFilename the name of the shortcut XML file, or null if there is none. * @param bigramXmlFilename the name of the bigram XML file. Pass null if there are no bigrams. * @return the read dictionary. * @throws FileNotFoundException if one of the files can't be found @@ -200,12 +246,14 @@ public class DictionaryMaker { * @throws ParserConfigurationException if the system can't create a SAX parser */ private static FusionDictionary readXmlFile(final String unigramXmlFilename, - final String bigramXmlFilename) throws FileNotFoundException, SAXException, - IOException, ParserConfigurationException { + final String shortcutXmlFilename, final String bigramXmlFilename) + throws FileNotFoundException, SAXException, IOException, ParserConfigurationException { final FileInputStream unigrams = new FileInputStream(new File(unigramXmlFilename)); + final FileInputStream shortcuts = null == shortcutXmlFilename ? null : + new FileInputStream(new File(shortcutXmlFilename)); final FileInputStream bigrams = null == bigramXmlFilename ? null : new FileInputStream(new File(bigramXmlFilename)); - return XmlDictInputOutput.readDictionaryXml(unigrams, bigrams); + return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams); } /** @@ -218,9 +266,13 @@ public class DictionaryMaker { * @throws IOException if one of the output files can't be written to. */ private static void writeOutputToParsedArgs(final Arguments args, final FusionDictionary dict) - throws FileNotFoundException, IOException { + throws FileNotFoundException, IOException, UnsupportedFormatException, + IllegalArgumentException { if (null != args.mOutputBinary) { - writeBinaryDictionary(args.mOutputBinary, dict); + writeBinaryDictionary(args.mOutputBinary, dict, 2); + } + if (null != args.mOutputBinaryFormat1) { + writeBinaryDictionary(args.mOutputBinaryFormat1, dict, 1); } if (null != args.mOutputXml) { writeXmlDictionary(args.mOutputXml, dict); @@ -232,13 +284,16 @@ public class DictionaryMaker { * * @param outputFilename the name of the file to write to. * @param dict the dictionary to write. + * @param version the binary format version to use. * @throws FileNotFoundException if the output file can't be created. * @throws IOException if the output file can't be written to. */ private static void writeBinaryDictionary(final String outputFilename, - final FusionDictionary dict) throws FileNotFoundException, IOException { + final FusionDictionary dict, final int version) + throws FileNotFoundException, IOException, UnsupportedFormatException { final File outputFile = new File(outputFilename); - BinaryDictInputOutput.writeDictionaryBinary(new FileOutputStream(outputFilename), dict); + BinaryDictInputOutput.writeDictionaryBinary(new FileOutputStream(outputFilename), dict, + version); } /** diff --git a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java index f6220eea2..08143d3ea 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java +++ b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java @@ -68,7 +68,7 @@ public class FusionDictionary implements Iterable<Word> { } /** - * A group of characters, with a frequency, shortcuts, bigrams, and children. + * A group of characters, with a frequency, shortcut targets, bigrams, and children. * * This is the central class of the in-memory representation. A CharGroup is what can * be seen as a traditional "trie node", except it can hold several characters at the @@ -82,25 +82,39 @@ public class FusionDictionary implements Iterable<Word> { public static class CharGroup { public static final int NOT_A_TERMINAL = -1; final int mChars[]; + final ArrayList<WeightedString> mShortcutTargets; final ArrayList<WeightedString> mBigrams; final int mFrequency; // NOT_A_TERMINAL == mFrequency indicates this is not a terminal. + final boolean mIsShortcutOnly; // Only valid if this is a terminal. Node mChildren; // The two following members to help with binary generation int mCachedSize; int mCachedAddress; - public CharGroup(final int[] chars, - final ArrayList<WeightedString> bigrams, final int frequency) { + public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets, + final ArrayList<WeightedString> bigrams, final int frequency, + final boolean isShortcutOnly) { mChars = chars; mFrequency = frequency; + mIsShortcutOnly = isShortcutOnly; + if (mIsShortcutOnly && NOT_A_TERMINAL == mFrequency) { + throw new RuntimeException("A node must be a terminal to be a shortcut only"); + } + mShortcutTargets = shortcutTargets; mBigrams = bigrams; mChildren = null; } - public CharGroup(final int[] chars, - final ArrayList<WeightedString> bigrams, final int frequency, final Node children) { + public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets, + final ArrayList<WeightedString> bigrams, final int frequency, final Node children, + final boolean isShortcutOnly) { mChars = chars; mFrequency = frequency; + mIsShortcutOnly = isShortcutOnly; + if (mIsShortcutOnly && NOT_A_TERMINAL == mFrequency) { + throw new RuntimeException("A node must be a terminal to be a shortcut only"); + } + mShortcutTargets = shortcutTargets; mBigrams = bigrams; mChildren = children; } @@ -150,13 +164,31 @@ public class FusionDictionary implements Iterable<Word> { static private int[] getCodePoints(String word) { final int wordLength = word.length(); int[] array = new int[word.codePointCount(0, wordLength)]; - for (int i = 0; i < wordLength; ++i) { + for (int i = 0; i < wordLength; i = word.offsetByCodePoints(i, 1)) { array[i] = word.codePointAt(i); } return array; } /** + * Helper method to add all words in a list as 0-frequency entries + * + * These words are added when shortcuts targets or bigrams are not found in the dictionary + * yet. The same words may be added later with an actual frequency - this is handled by + * the private version of add(). + */ + private void addNeutralWords(final ArrayList<WeightedString> words) { + if (null != words) { + for (WeightedString word : words) { + final CharGroup t = findWordInTree(mRoot, word.mWord); + if (null == t) { + add(getCodePoints(word.mWord), 0, null, null, false /* isShortcutOnly */); + } + } + } + } + + /** * Helper method to add a word as a string. * * This method adds a word to the dictionary with the given frequency. Optional @@ -165,18 +197,19 @@ public class FusionDictionary implements Iterable<Word> { * * @param word the word to add. * @param frequency the frequency of the word, in the range [0..255]. + * @param shortcutTargets a list of shortcut targets for this word, or null. * @param bigrams a list of bigrams, or null. */ - public void add(String word, int frequency, ArrayList<WeightedString> bigrams) { + public void add(final String word, final int frequency, + final ArrayList<WeightedString> shortcutTargets, + final ArrayList<WeightedString> bigrams) { + if (null != shortcutTargets) { + addNeutralWords(shortcutTargets); + } if (null != bigrams) { - for (WeightedString bigram : bigrams) { - final CharGroup t = findWordInTree(mRoot, bigram.mWord); - if (null == t) { - add(getCodePoints(bigram.mWord), 0, null); - } - } + addNeutralWords(bigrams); } - add(getCodePoints(word), frequency, bigrams); + add(getCodePoints(word), frequency, shortcutTargets, bigrams, false /* isShortcutOnly */); } /** @@ -198,16 +231,37 @@ public class FusionDictionary implements Iterable<Word> { } /** + * Helper method to add a shortcut that should not be a dictionary word. + * + * @param word the word to add. + * @param frequency the frequency of the word, in the range [0..255]. + * @param shortcutTargets a list of shortcut targets. May not be null. + */ + public void addShortcutOnly(final String word, final int frequency, + final ArrayList<WeightedString> shortcutTargets) { + if (null == shortcutTargets) { + throw new RuntimeException("Can't add a shortcut without targets"); + } + addNeutralWords(shortcutTargets); + add(getCodePoints(word), frequency, shortcutTargets, null, true /* isShortcutOnly */); + } + + /** * Add a word to this dictionary. * - * The bigrams, if any, have to be in the dictionary already. If they aren't, + * The shortcuts and bigrams, if any, have to be in the dictionary already. If they aren't, * an exception is thrown. * * @param word the word, as an int array. * @param frequency the frequency of the word, in the range [0..255]. + * @param shortcutTargets an optional list of shortcut targets for this word (null if none). * @param bigrams an optional list of bigrams for this word (null if none). + * @param isShortcutOnly whether this should be a shortcut only. */ - private void add(int[] word, int frequency, ArrayList<WeightedString> bigrams) { + private void add(final int[] word, final int frequency, + final ArrayList<WeightedString> shortcutTargets, + final ArrayList<WeightedString> bigrams, + final boolean isShortcutOnly) { assert(frequency >= 0 && frequency <= 255); Node currentNode = mRoot; int charIndex = 0; @@ -231,7 +285,8 @@ public class FusionDictionary implements Iterable<Word> { // No node at this point to accept the word. Create one. final int insertionIndex = findInsertionIndex(currentNode, word[charIndex]); final CharGroup newGroup = new CharGroup( - Arrays.copyOfRange(word, charIndex, word.length), bigrams, frequency); + Arrays.copyOfRange(word, charIndex, word.length), + shortcutTargets, bigrams, frequency, isShortcutOnly); currentNode.mData.add(insertionIndex, newGroup); checkStack(currentNode); } else { @@ -245,7 +300,8 @@ public class FusionDictionary implements Iterable<Word> { + new String(word, 0, word.length)); } else { final CharGroup newNode = new CharGroup(currentGroup.mChars, - bigrams, frequency, currentGroup.mChildren); + shortcutTargets, bigrams, frequency, currentGroup.mChildren, + isShortcutOnly); currentNode.mData.set(nodeIndex, newNode); checkStack(currentNode); } @@ -254,13 +310,13 @@ public class FusionDictionary implements Iterable<Word> { // We only have to create a new node and add it to the end of this. final CharGroup newNode = new CharGroup( Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length), - bigrams, frequency); + shortcutTargets, bigrams, frequency, isShortcutOnly); currentGroup.mChildren = new Node(); currentGroup.mChildren.mData.add(newNode); } } else { if (0 == differentCharIndex) { - // Exact same word. Check the frequency is 0 or -1, and update. + // Exact same word. Check the frequency is 0 or NOT_A_TERMINAL, and update. if (0 != frequency) { if (0 < currentGroup.mFrequency) { throw new RuntimeException("This word already exists with frequency " @@ -268,7 +324,9 @@ public class FusionDictionary implements Iterable<Word> { + new String(word, 0, word.length)); } final CharGroup newGroup = new CharGroup(word, - currentGroup.mBigrams, frequency, currentGroup.mChildren); + currentGroup.mShortcutTargets, currentGroup.mBigrams, + frequency, currentGroup.mChildren, + currentGroup.mIsShortcutOnly && isShortcutOnly); currentNode.mData.set(nodeIndex, newGroup); } } else { @@ -277,22 +335,27 @@ public class FusionDictionary implements Iterable<Word> { Node newChildren = new Node(); final CharGroup newOldWord = new CharGroup( Arrays.copyOfRange(currentGroup.mChars, differentCharIndex, - currentGroup.mChars.length), - currentGroup.mBigrams, currentGroup.mFrequency, currentGroup.mChildren); + currentGroup.mChars.length), currentGroup.mShortcutTargets, + currentGroup.mBigrams, currentGroup.mFrequency, currentGroup.mChildren, + currentGroup.mIsShortcutOnly); newChildren.mData.add(newOldWord); final CharGroup newParent; if (charIndex + differentCharIndex >= word.length) { newParent = new CharGroup( Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex), - bigrams, frequency, newChildren); + shortcutTargets, bigrams, frequency, newChildren, isShortcutOnly); } else { + // isShortcutOnly makes no sense for non-terminal nodes. The following node + // is non-terminal (frequency 0 in FusionDictionary representation) so we + // pass false for isShortcutOnly newParent = new CharGroup( Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex), - null, -1, newChildren); + null, null, -1, newChildren, false /* isShortcutOnly */); final CharGroup newWord = new CharGroup( Arrays.copyOfRange(word, charIndex + differentCharIndex, - word.length), bigrams, frequency); + word.length), shortcutTargets, bigrams, frequency, + isShortcutOnly); final int addIndex = word[charIndex + differentCharIndex] > currentGroup.mChars[differentCharIndex] ? 1 : 0; newChildren.mData.add(addIndex, newWord); @@ -355,7 +418,8 @@ public class FusionDictionary implements Iterable<Word> { */ private static int findInsertionIndex(final Node node, int character) { final List data = node.mData; - final CharGroup reference = new CharGroup(new int[] { character }, null, 0); + final CharGroup reference = new CharGroup(new int[] { character }, null, null, 0, + false /* isShortcutOnly */); int result = Collections.binarySearch(data, reference, CHARGROUP_COMPARATOR); return result >= 0 ? result : -result - 1; } @@ -399,6 +463,16 @@ public class FusionDictionary implements Iterable<Word> { } /** + * Helper method to find out whether a word is in the dict or not. + */ + public boolean hasWord(final String s) { + if (null == s || "".equals(s)) { + throw new RuntimeException("Can't search for a null or empty string"); + } + return null != findWordInTree(mRoot, s); + } + + /** * Recursively count the number of character groups in a given branch of the trie. * * @param node the parent node. @@ -573,7 +647,8 @@ public class FusionDictionary implements Iterable<Word> { } if (currentGroup.mFrequency >= 0) return new Word(mCurrentString.toString(), currentGroup.mFrequency, - currentGroup.mBigrams); + currentGroup.mShortcutTargets, currentGroup.mBigrams, + currentGroup.mIsShortcutOnly); } else { mPositions.removeLast(); currentPos = mPositions.getLast(); diff --git a/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java b/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java index e50202184..cf66eef4b 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java +++ b/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java @@ -19,7 +19,7 @@ package com.android.inputmethod.latin; /** * A not-yet-resolved attribute. * - * An attribute is either a bigram or an shortcut. + * An attribute is either a bigram or a shortcut. * All instances of this class are always immutable. */ public class PendingAttribute { diff --git a/tools/makedict/src/com/android/inputmethod/latin/Word.java b/tools/makedict/src/com/android/inputmethod/latin/Word.java index 916165a41..cf6116f91 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/Word.java +++ b/tools/makedict/src/com/android/inputmethod/latin/Word.java @@ -28,12 +28,18 @@ import java.util.ArrayList; public class Word implements Comparable<Word> { final String mWord; final int mFrequency; + final boolean mIsShortcutOnly; + final ArrayList<WeightedString> mShortcutTargets; final ArrayList<WeightedString> mBigrams; - public Word(String word, int frequency, ArrayList<WeightedString> bigrams) { + public Word(final String word, final int frequency, + final ArrayList<WeightedString> shortcutTargets, + final ArrayList<WeightedString> bigrams, final boolean isShortcutOnly) { mWord = word; mFrequency = frequency; + mShortcutTargets = shortcutTargets; mBigrams = bigrams; + mIsShortcutOnly = isShortcutOnly; } /** @@ -60,6 +66,7 @@ public class Word implements Comparable<Word> { if (!(o instanceof Word)) return false; Word w = (Word)o; return mFrequency == w.mFrequency && mWord.equals(w.mWord) + && mShortcutTargets.equals(w.mShortcutTargets) && mBigrams.equals(w.mBigrams); } } diff --git a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java index 35a7b51d6..77c536668 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java +++ b/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java @@ -42,8 +42,12 @@ public class XmlDictInputOutput { private static final String WORD_TAG = "w"; private static final String BIGRAM_TAG = "bigram"; + private static final String SHORTCUT_TAG = "shortcut"; private static final String FREQUENCY_ATTR = "f"; private static final String WORD_ATTR = "word"; + private static final String SHORTCUT_ONLY_ATTR = "shortcutOnly"; + + private static final int SHORTCUT_ONLY_DEFAULT_FREQ = 1; /** * SAX handler for a unigram XML file. @@ -61,6 +65,7 @@ public class XmlDictInputOutput { int mState; // the state of the parser int mFreq; // the currently read freq String mWord; // the current word + final HashMap<String, ArrayList<WeightedString>> mShortcutsMap; final HashMap<String, ArrayList<WeightedString>> mBigramsMap; /** @@ -69,9 +74,11 @@ public class XmlDictInputOutput { * @param dict the dictionary to construct. * @param bigrams the bigrams as a map. This may be empty, but may not be null. */ - public UnigramHandler(FusionDictionary dict, - HashMap<String, ArrayList<WeightedString>> bigrams) { + public UnigramHandler(final FusionDictionary dict, + final HashMap<String, ArrayList<WeightedString>> shortcuts, + final HashMap<String, ArrayList<WeightedString>> bigrams) { mDictionary = dict; + mShortcutsMap = shortcuts; mBigramsMap = bigrams; mWord = ""; mState = START; @@ -107,47 +114,96 @@ public class XmlDictInputOutput { @Override public void endElement(String uri, String localName, String qName) { if (WORD == mState) { - mDictionary.add(mWord, mFreq, mBigramsMap.get(mWord)); + mDictionary.add(mWord, mFreq, mShortcutsMap.get(mWord), mBigramsMap.get(mWord)); mState = START; } } } + static private class AssociativeListHandler extends DefaultHandler { + private final String SRC_TAG; + private final String SRC_ATTRIBUTE; + private final String DST_TAG; + private final String DST_ATTRIBUTE; + private final String DST_FREQ; + + // In this version of the XML file, the bigram frequency is given as an int 0..XML_MAX + private final static int XML_MAX = 256; + // In memory and in the binary dictionary the bigram frequency is 0..MEMORY_MAX + private final static int MEMORY_MAX = 16; + private final static int XML_TO_MEMORY_RATIO = XML_MAX / MEMORY_MAX; + + private String mSrc; + private final HashMap<String, ArrayList<WeightedString>> mAssocMap; + + public AssociativeListHandler(final String srcTag, final String srcAttribute, + final String dstTag, final String dstAttribute, final String dstFreq) { + SRC_TAG = srcTag; + SRC_ATTRIBUTE = srcAttribute; + DST_TAG = dstTag; + DST_ATTRIBUTE = dstAttribute; + DST_FREQ = dstFreq; + mSrc = null; + mAssocMap = new HashMap<String, ArrayList<WeightedString>>(); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) { + if (SRC_TAG.equals(localName)) { + mSrc = attrs.getValue(uri, SRC_ATTRIBUTE); + } else if (DST_TAG.equals(localName)) { + String dst = attrs.getValue(uri, DST_ATTRIBUTE); + int freq = Integer.parseInt(attrs.getValue(uri, DST_FREQ)); + WeightedString bigram = new WeightedString(dst, freq / XML_TO_MEMORY_RATIO); + ArrayList<WeightedString> bigramList = mAssocMap.get(mSrc); + if (null == bigramList) bigramList = new ArrayList<WeightedString>(); + bigramList.add(bigram); + mAssocMap.put(mSrc, bigramList); + } + } + + public HashMap<String, ArrayList<WeightedString>> getAssocMap() { + return mAssocMap; + } + } + /** * SAX handler for a bigram XML file. */ - static private class BigramHandler extends DefaultHandler { + static private class BigramHandler extends AssociativeListHandler { private final static String BIGRAM_W1_TAG = "bi"; private final static String BIGRAM_W2_TAG = "w"; private final static String BIGRAM_W1_ATTRIBUTE = "w1"; private final static String BIGRAM_W2_ATTRIBUTE = "w2"; private final static String BIGRAM_FREQ_ATTRIBUTE = "p"; - String mW1; - final HashMap<String, ArrayList<WeightedString>> mBigramsMap; - public BigramHandler() { - mW1 = null; - mBigramsMap = new HashMap<String, ArrayList<WeightedString>>(); + super(BIGRAM_W1_TAG, BIGRAM_W1_ATTRIBUTE, BIGRAM_W2_TAG, BIGRAM_W2_ATTRIBUTE, + BIGRAM_FREQ_ATTRIBUTE); } - @Override - public void startElement(String uri, String localName, String qName, Attributes attrs) { - if (BIGRAM_W1_TAG.equals(localName)) { - mW1 = attrs.getValue(uri, BIGRAM_W1_ATTRIBUTE); - } else if (BIGRAM_W2_TAG.equals(localName)) { - String w2 = attrs.getValue(uri, BIGRAM_W2_ATTRIBUTE); - int freq = Integer.parseInt(attrs.getValue(uri, BIGRAM_FREQ_ATTRIBUTE)); - WeightedString bigram = new WeightedString(w2, freq / 8); - ArrayList<WeightedString> bigramList = mBigramsMap.get(mW1); - if (null == bigramList) bigramList = new ArrayList<WeightedString>(); - bigramList.add(bigram); - mBigramsMap.put(mW1, bigramList); - } + public HashMap<String, ArrayList<WeightedString>> getBigramMap() { + return getAssocMap(); } + } - public HashMap<String, ArrayList<WeightedString>> getBigramMap() { - return mBigramsMap; + /** + * SAX handler for a shortcut XML file. + */ + static private class ShortcutHandler extends AssociativeListHandler { + private final static String ENTRY_TAG = "entry"; + private final static String ENTRY_ATTRIBUTE = "shortcut"; + private final static String TARGET_TAG = "target"; + private final static String REPLACEMENT_ATTRIBUTE = "replacement"; + private final static String TARGET_PRIORITY_ATTRIBUTE = "priority"; + + public ShortcutHandler() { + super(ENTRY_TAG, ENTRY_ATTRIBUTE, TARGET_TAG, REPLACEMENT_ATTRIBUTE, + TARGET_PRIORITY_ATTRIBUTE); + } + + public HashMap<String, ArrayList<WeightedString>> getShortcutMap() { + return getAssocMap(); } } @@ -158,9 +214,12 @@ public class XmlDictInputOutput { * representation. * * @param unigrams the file to read the data from. + * @param shortcuts the file to read the shortcuts from, or null. + * @param bigrams the file to read the bigrams from, or null. * @return the in-memory representation of the dictionary. */ - public static FusionDictionary readDictionaryXml(InputStream unigrams, InputStream bigrams) + public static FusionDictionary readDictionaryXml(final InputStream unigrams, + final InputStream shortcuts, final InputStream bigrams) throws SAXException, IOException, ParserConfigurationException { final SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); @@ -168,10 +227,23 @@ public class XmlDictInputOutput { final BigramHandler bigramHandler = new BigramHandler(); if (null != bigrams) parser.parse(bigrams, bigramHandler); + final ShortcutHandler shortcutHandler = new ShortcutHandler(); + if (null != shortcuts) parser.parse(shortcuts, shortcutHandler); + final FusionDictionary dict = new FusionDictionary(); final UnigramHandler unigramHandler = - new UnigramHandler(dict, bigramHandler.getBigramMap()); + new UnigramHandler(dict, shortcutHandler.getShortcutMap(), + bigramHandler.getBigramMap()); parser.parse(unigrams, unigramHandler); + + final HashMap<String, ArrayList<WeightedString>> shortcutMap = + shortcutHandler.getShortcutMap(); + for (final String shortcut : shortcutMap.keySet()) { + if (dict.hasWord(shortcut)) continue; + // TODO: list a frequency in the shortcut file and use it here, instead of + // a constant freq + dict.addShortcutOnly(shortcut, SHORTCUT_ONLY_DEFAULT_FREQ, shortcutMap.get(shortcut)); + } return dict; } @@ -204,9 +276,20 @@ public class XmlDictInputOutput { } // TODO: use an XMLSerializer if this gets big destination.write("<wordlist format=\"2\">\n"); + destination.write("<!-- Warning: there is no code to read this format yet. -->\n"); for (Word word : set) { destination.write(" <" + WORD_TAG + " " + WORD_ATTR + "=\"" + word.mWord + "\" " - + FREQUENCY_ATTR + "=\"" + word.mFrequency + "\">"); + + FREQUENCY_ATTR + "=\"" + word.mFrequency + "\" " + SHORTCUT_ONLY_ATTR + + "=\"" + word.mIsShortcutOnly + "\">"); + if (null != word.mShortcutTargets) { + destination.write("\n"); + for (WeightedString target : word.mShortcutTargets) { + destination.write(" <" + SHORTCUT_TAG + " " + FREQUENCY_ATTR + "=\"" + + target.mFrequency + "\">" + target.mWord + "</" + SHORTCUT_TAG + + ">\n"); + } + destination.write(" "); + } if (null != word.mBigrams) { destination.write("\n"); for (WeightedString bigram : word.mBigrams) { diff --git a/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java b/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java index 79cf14b2b..6ac046bbf 100644 --- a/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java +++ b/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java @@ -39,11 +39,11 @@ public class BinaryDictInputOutputTest extends TestCase { // that it does not contain any duplicates. public void testFlattenNodes() { final FusionDictionary dict = new FusionDictionary(); - dict.add("foo", 1, null); - dict.add("fta", 1, null); - dict.add("ftb", 1, null); - dict.add("bar", 1, null); - dict.add("fool", 1, null); + dict.add("foo", 1, null, null); + dict.add("fta", 1, null, null); + dict.add("ftb", 1, null, null); + dict.add("bar", 1, null, null); + dict.add("fool", 1, null, null); final ArrayList<Node> result = BinaryDictInputOutput.flattenTree(dict.mRoot); assertEquals(4, result.size()); while (!result.isEmpty()) { |